题目链接: http://poj.org/problem?id=1330
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 23822 | Accepted: 12405 |
Description
Input
Output
Sample Input
2 16 1 14 8 5 10 16 5 9 4 6 8 4 4 10 1 13 6 15 10 11 6 7 10 2 16 3 8 1 16 12 16 7 5 2 3 3 4 3 1 1 5 3 5
Sample Output
4 3
题意:
给一棵树,再给两节点,求两节点的最近公共祖先。
本题有暴力解,在线,离线三种解法。这里提供前两种。
代码1:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define N 10010 struct Node { int parents; int flag; }tree[N]; void init(int n) { for(int i=1;i<=n;i++) { tree[i].flag=0; tree[i].parents=i; } } void update(int s,int e) { tree[e].parents=s; } void LCA(int s,int e) { tree[s].flag=1; while(tree[s].parents!=s) { s=tree[s].parents; tree[s].flag=1; } int num; while(tree[e].parents!=e) { if(tree[e].flag) { num=e; break; } e=tree[e].parents; } if(tree[e].flag) num=e; printf("%d\n",num); } int main() { int T,n; int s,e; scanf("%d",&T); while(T--) { scanf("%d",&n); init(n); for(int i=1;i<n;i++) { scanf("%d %d",&s,&e); update(s,e); } scanf("%d %d",&s,&e); LCA(s,e); } return 0; }代码2:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define N 10010 int dp[2*N][20]; int head[N],p[N]; int dep[2*N],f[2*N]; int flag[N],cnt; struct Edge { int to,next; } edge[2*N]; void init(int n) { cnt=0; for(int i=0; i<=n; i++) { head[i]=-1; flag[i]=0; } } void addedge(int s,int e) { edge[cnt].to=e; edge[cnt].next=head[s]; head[s]=cnt++; } void dfs(int u,int d) { f[cnt]=u; dep[cnt]=d; p[u]=cnt++; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].to; dfs(v,d+1); f[cnt]=u; dep[cnt++]=d; } } void makermq() { for(int i=0; i<cnt; i++) dp[i][0]=i; for(int j=1; (1<<j)<=cnt; j++) { for(int i=0; i+(1<<j)-1<cnt; i++) { if(dep[dp[i][j-1]]<dep[dp[i+(1<<(j-1))][j-1]]) dp[i][j]=dp[i][j-1]; else dp[i][j]=dp[i+(1<<(j-1))][j-1]; } } } int finds(int s,int e) { if(s>e) { int t=s; s=e; e=t; } int k=(int)(log(e-s+1.0)/log(2.0)); if(dep[dp[s][k]]<dep[dp[e-(1<<k)+1][k]]) return dp[s][k]; return dp[e-(1<<k)+1][k]; } void LCA(int root,int n) { cnt=0; dfs(root,0); makermq(); int s,e; scanf("%d %d",&s,&e); printf("%d\n",f[finds(p[s],p[e])]); } int main() { int T,n; int s,e,root; scanf("%d",&T); while(T--) { scanf("%d",&n); init(n); for(int i=1; i<n; i++) { scanf("%d %d",&s,&e); addedge(s,e); flag[e]=1; } for(int i=1; i<=n; i++) if(!flag[i]) { root=i; break; } LCA(root,n); } return 0; }