您的位置:首页 > 其它

PAT 1021. Deepest Root

2014-03-04 11:12 197 查看
题目:http://pat.zju.edu.cn/contests/pat-a-practise/1021

题意:N个节点,给出N-1条边。要求判断是否为树,若不为树,输出有几个连通分量;若为树,输出符合条件的树根,即以该节点为跟能够得到最大树深。

思路:先用并查集判断是否为树,不为树则根据f [ i ]==i 得到连通分量数; 若为树,则任意从一个节点开始深度搜索,找到此时深度最大的节点maxpoint,此时的maxpoint即为符合题意的根节点之一。然后从maxpoint进行第二次深度搜索,得到深度最大的节点均可作为符合题意的根节点。

N==1时要特判。

代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
vector<int> map[10001];
int f[10001],maxpoint,maxdep;
bool vis[10001];
struct cmpp
{
    bool operator()(int x,int y)
	{
	   return x>y;
	}
};
priority_queue<int,vector<int>,cmpp> q;
int find(int a)
{
   if(f[a]==a) return a;
   return find(f[a]);
}
void Union(int a,int b)
{
    f[b]=find(a);
}
void dfs(int node,int dep)
{
	vis[node]=false;
	if(dep==maxdep) q.push(node);
        if(dep>maxdep)
	{
		while(!q.empty())
		{
		   q.pop();
		}
		q.push(node);
		maxdep=dep;
		maxpoint=node;
	}	
	int len=map[node].size(),i;
	for(i=0;i<len;i++)
		if(vis[map[node][i]])
		    dfs(map[node][i],dep+1);
}
int main()
{
	int n,i,a,b;
	scanf("%d",&n);
	if(n==1) 
	{
	    printf("1\n");return 0;
	}
	for(i=1;i<=n;i++)
		f[i]=i;
	for(i=1;i<n;i++)
	{
	    scanf("%d%d",&a,&b);
		Union(a,b);
		map[a].push_back(b);
		map[b].push_back(a);
	}
	int count=0;
	for(i=1;i<=n;i++)
		if(f[i]==i) count++;
	if(count>1) printf("Error: %d components\n",count);
	else 
	{
		while(!q.empty())
			q.pop();
		maxdep=0;
		maxpoint=1;
		memset(vis,true,sizeof(vis));
	        dfs(1,0);
		memset(vis,true,sizeof(vis));
		int tmp=maxpoint;
		dfs(maxpoint,0);
		q.push(tmp);              //别忘加入根节点!!!
		while(!q.empty())
		{
		    printf("%d\n",q.top());
			q.pop();
		}
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: