呵呵,这道题目的话,跟之前那道计算路径程度有点区别
给你多个路径,让你求出哪些节点被作为最近公共祖先,并计算被作为最近公共祖先的次数
首先,读入数据有点麻烦,按代码中那种方法,还蛮方便的
其次就是,需要找出根节点,再进行深度优先搜索,这是很求路径长度唯一的区别,计算路径的时候,从任意节点开始,并不影响计算路径的长度
但是,此题目中,我们要保证每一个最近公共祖先都是正确的,为什么这么说呢?因为,在计算路径的时候,其实只是一种相对的情况,即,这已遍历的节点中,相对的某个节点是最近公共祖先,没有一种严格性
而此题就是要求最近公共祖先,所以必须先找出根节点,即入度为零的节点,这个也很好理解
具体的,见之前的2586吧
#include<stdio.h> #include<string.h> #include<stdlib.h> #define MAXN 910 int first[MAXN],head[MAXN],cnt[MAXN],f[MAXN]; int visited[MAXN]; struct node { int vex,next; }g[MAXN*2]; struct node1 { int vex,next; }q[MAXN*MAXN]; int find(int x) { if(x==f[x]) return f[x]; f[x]=find(f[x]); return f[x]; } void add(int v,int w,int &j) { g[j].vex=w; g[j].next=first[v]; first[v]=j++; } void add2(int v,int w,int &j) { q[j].vex=w; q[j].next=head[v]; head[v]=j++; } void DFS(int v) { f[v]=v; visited[v]=1; int i; for(i=head[v];i!=-1;i=q[i].next) if(visited[q[i].vex])//已访问 { cnt[find(q[i].vex)]++; } for(i=first[v];i!=-1;i=g[i].next) { if(!visited[g[i].vex]) { DFS(g[i].vex); f[g[i].vex]=v; } } } int main() { int m,n,i,t,v,w,j,k; int flag[MAXN]; char ch; while(scanf("%d",&n)!=EOF) { k=n; memset(first,-1,sizeof(first)); memset(head,-1,sizeof(head)); memset(visited,0,sizeof(visited)); memset(cnt,0,sizeof(cnt)); memset(flag,0,sizeof(flag)); j=0; while(k--) { scanf("%d",&v); while(getchar()!='(');//很不错的读入方法 scanf("%d",&t); while(getchar()!=')'); while(t--) { scanf("%d",&w); add(v,w,j); add(w,v,j); flag[w]=1; } } scanf("%d",&m); for(i=j=0;i<m;i++) { while(getchar()!='('); scanf("%d %d",&v,&w); while(getchar()!=')'); add2(v,w,j); add2(w,v,j); } for(i=1;i<=n;i++) if(flag[i]==0)//入度为0 break; DFS(i); for(i=1;i<=n;i++) if(cnt[i]) printf("%d:%d\n",i,cnt[i]); } return 0; }