pku1470 Closest Common Ancestors

呵呵,这道题目的话,跟之前那道计算路径程度有点区别

给你多个路径,让你求出哪些节点被作为最近公共祖先,并计算被作为最近公共祖先的次数

首先,读入数据有点麻烦,按代码中那种方法,还蛮方便的

其次就是,需要找出根节点,再进行深度优先搜索,这是很求路径长度唯一的区别,计算路径的时候,从任意节点开始,并不影响计算路径的长度

但是,此题目中,我们要保证每一个最近公共祖先都是正确的,为什么这么说呢?因为,在计算路径的时候,其实只是一种相对的情况,即,这已遍历的节点中,相对的某个节点是最近公共祖先,没有一种严格性

而此题就是要求最近公共祖先,所以必须先找出根节点,即入度为零的节点,这个也很好理解

具体的,见之前的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;
}
原文地址:https://www.cnblogs.com/nanke/p/2040679.html