WJC上学记
WJC上學記
題目描述:
WJC為了追求YHY,決定考上樹人,但是,愚蠢的他沒有足夠好的成績,只能靠自己的親戚來幫忙。但是由于他足夠愚蠢,連自己的親戚都不認識,仁慈而被樹人優錄的Geek_du決定幫助他。WJC找了N(0<N<50000)個人,分別和他們進行聊天,聊了E次(0<E<30000)。請幫助WJC找到一些人和他自己的最近公共祖先。
輸入說明:
輸入第一行包含兩個整數,N和E。分別表示N個人和E次聊天。
以下E行每一行包含兩個整數,A,B表示A是B的父輩。
再下面一行包含一個整數M,表明M次查詢。
下面M行每行包含兩個整數,P,Q,詢問P和Q的最近公共祖先。
輸出說明:
對于每個查詢,給出他們的最近公共祖先。
樣例輸入:
4 3
1 2
2 3
2 4
1
3 4
樣例輸出:
2
數據范圍:
100%:0<N<5000,0<E<30000
LCA最近公共祖先模板題
/* ***********************************************
Author :buaaasd
Created Time :2016/1/23 19:48:00
File Name :1.cpp
************************************************ */
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <iomanip>
#include <list>
#include <deque>
#include <stack>
#define ull unsigned long long
#define ll long long
#define mod 90001
#define INF 0x3f3f3f3f
#define maxn 100000+10
#define cle(a) memset(a,0,sizeof(a))
const ull inf = 1LL << 61;
const double eps=1e-5;
using namespace std;
bool cmp(int a,int b){
return a>b;
}
int fa[maxn],n,m,pre[maxn],l;
int qpre[maxn];
int ans[maxn*10];
struct node{
int v,next;
}edge[maxn+10];
struct Node{
int qv,qnext,id;
}qedge[maxn*10];
void add(int u,int v){
edge[l].v=v;
edge[l].next=pre[u];
pre[u]=l++;
}
void qadd(int u,int v,int id){
qedge[l].qv=v;
qedge[l].id=id;
qedge[l].qnext=qpre[u];
qpre[u]=l++;
}
int findfa(int x){
if(x==fa[x])return x;
else return fa[x]=findfa(fa[x]);
}
void Union(int x,int y){
x=findfa(x);
y=findfa(y);
fa[y]=x;
}
void dfs(int u){
int v;
fa[u]=u;
for(int i=pre[u];i+1;i=edge[i].next){
v=edge[i].v;
if(fa[v]==-1){
dfs(v);
Union(u,v);
}
}
/*
for(v=1;v<=n;v++){
if(fa[v]!=-1){
lca[u][v]=lca[v][u]=findfa(v);
}
}*/
for(int i=qpre[u];i+1;i=qedge[i].qnext){
v=qedge[i].qv;
if(fa[v]!=-1){
int id=qedge[i].id;
ans[id]=findfa(v);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
//freopen("in.txt","r",stdin);
#endif
//freopen("out.txt","w",stdout);
int x,y;
while(cin>>n>>m){
l=0;
memset(fa,-1,sizeof fa);
memset(pre,-1,sizeof pre);
memset(qpre,-1,sizeof qpre);
for(int i=1;i<=m;i++){
cin>>x>>y;
add(x,y);
}
l=0;
int k;
cin>>k;
for(int i=1;i<=k;i++){
scanf("%d%d",&x,&y);
qadd(x,y,i);
qadd(y,x,i);
}
dfs(1);
for(int i=1;i<=k;i++){
printf("%d
",ans[i]);
}
}
return 0;
}
借鑒了網上的許多代碼,最后總結的模板。
這個博主寫的最清晰。https://comzyh.com/blog/archives/492/ 而且有圖真是極好的。
鏈式前向星pre[u]代表以u為起點的第一條邊的位置。edge[l].v存儲邊的終點。edge[l].next存儲下一條邊的位置。
總結
- 上一篇: zotero zotfile插件 pdf
- 下一篇: 单机游戏存档修改