呵呵,这道题目的话,跟之前那道计算路径程度有点区别
给你多个路径,让你求出哪些节点被作为最近公共祖先,并计算被作为最近公共祖先的次数
首先,读入数据有点麻烦,按代码中那种方法,还蛮方便的
其次就是,需要找出根节点,再进行深度优先搜索,这是很求路径长度唯一的区别,计算路径的时候,从任意节点开始,并不影响计算路径的长度
但是,此题目中,我们要保证每一个最近公共祖先都是正确的,为什么这么说呢?因为,在计算路径的时候,其实只是一种相对的情况,即,这已遍历的节点中,相对的某个节点是最近公共祖先,没有一种严格性
而此题就是要求最近公共祖先,所以必须先找出根节点,即入度为零的节点,这个也很好理解
具体的,见之前的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;
}