poj 1330 LCM 离线算法
http://poj.org/problem?id=1330 题目
1: #include<stdio.h>
2: #include<string.h>
3: #include<iostream>
4: #include<vector>
5: using namespace std;
6:
7: int n;
8: int fa[11111],ancestor[11111];
9: bool path[11111],indegree[11111];
10: int ans;
11: vector<int> son[11111];
12: int a,b;
13: void init(){for(int i=0;i<n;i++)fa[i]=i;}
14: int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
15: void merge(int x,int y)
16: {
17: int xx=find(x),yy=find(y);
18: if(xx!=yy)fa[yy]=xx;
19: }
20: void LCA(int x)
21: {
22: path[x]=true,ancestor[x]=x;//分割当前子树,即当前子树的祖先都只可能是x
23: for(std::vector<int>::iterator ii=son[x].begin();ii!=son[x].end();ii++)
24: {
25: int i=*ii;
26: LCA(i);//处理孩子节点的子树
27: merge(x,i);//将孩子节点并入x的树中
28: ancestor[find(x)]=x;//将将i节点的子树的祖先都更新为x
29: }
30: /****
31: 查询a和b的公共祖先时有两种情况
32: 1.a是b的直接祖先,
33: 这时首先在b节点进入判断,ancestor为a
34: 再次进入a节点判断 ancestors还是a;
35: 2.a和b属于一个公共祖先的两个子树上,(设a相对b在左边子树)
36: 这时先在a中做下列判断,发现path[b]为false,
37: 再在b中做下列判断,这时ancestors[a]已经更新为当前树的根节点了。
38: ****/
39: if(x==a&&path[b])
40: ans=ancestor[find(b)]+1;
41: else if(x==b&&path[a])
42: ans=ancestor[find(a)]+1;
43: }
44: int main()
45: {//freopen("in.txt","r",stdin);
46: int T;
47: scanf("%d",&T);
48: while(T--)
49: {
50: scanf("%d",&n);
51: memset(indegree,false,sizeof(indegree));
52: memset(path,false,sizeof(path));
53: for(int i=0;i<n;i++)son[i].clear();
54: init();
55: for(int i=1;i<n;i++)
56: scanf("%d%d",&a,&b),a--,b--,son[a].push_back(b),indegree[b]=true;
57: scanf("%d%d",&a,&b),a--,b--;
58: for(int i=0;i<n;i++)
59: if(!indegree[i]){LCA(i);break;}
60: cout<<ans<<endl;
61: }
62: return 0;
63: }