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\n",ans[i]); } } return 0; }
借鉴了网上的许多代码,最后总结的模板。
这个博主写的最清晰。https://comzyh.com/blog/archives/492/ 而且有图真是极好的。
链式前向星pre[u]代表以u为起点的第一条边的位置。edge[l].v存储边的终点。edge[l].next存储下一条边的位置。
原文地址:http://www.cnblogs.com/pk28/
与有肝胆人共事,从无字句处读书。
欢迎关注公众号:
欢迎关注公众号: