POJ 3107 - Godfather

 

题目地址: http://poj.org/problem?id=3107

 

DFS遍历。

 

利用树化区间的思想。

 

能想到这个方法,就很好做了。

 

枚举每一个节点为断点:

 

       1. 那么其每【一个子节点】=【一颗单独的树】。

 

       2. 而【整棵树】减去【以这个节点为根的树】=【单独一棵树】。

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#define bug puts("here");

using namespace std;

struct Edge{
	int gt,nx;
}edge[110000];
int ef[51000],tol;

void add_edge(int a,int b){
	edge[tol].gt=b;
	edge[tol].nx=ef[a];
	ef[a]=tol++;
}

int has[51000];
int lft[51000],rit[51000];
int now;
int father[51000];

void dfs(int x){
	int k;
	lft[x]=++now;
	has[x]=1;
	for(k=ef[x];k!=-1;k=edge[k].nx){
		if(has[edge[k].gt]) continue;
		dfs(edge[k].gt);
		father[edge[k].gt]=x;
	}
	rit[x]=now;
}

int res[51000],cnt;

int getlen(int x){
	return rit[x]-lft[x]+1;
}

int main(){
	int n,i,a,b,k,mn,tmp;
	scanf("%d",&n);
	memset(ef,-1,sizeof(ef));
	tol=0;
	for(i=1;i<n;i++){
		scanf("%d%d",&a,&b);
		add_edge(a,b);
		add_edge(b,a); 
	}
	now=0;
	dfs(1);
	father[1]=-1;
	for(i=1;i<=n;i++){
		if(father[i]==-1){
			mn=100000;
			tmp=0;
		}
		else{
			tmp=getlen(1)-getlen(i);
		}
		for(k=ef[i];k!=-1;k=edge[k].nx){
			if(father[i]==edge[k].gt) continue;
			if(tmp<getlen(edge[k].gt))
				tmp=getlen(edge[k].gt); 
		}
		if(tmp<mn){
			cnt=0;
			mn=tmp;
			res[cnt++]=i;
		}
		else if(tmp==mn){
			res[cnt++]=i;
		}
	}
	printf("%d",res[0]);
	for(i=1;i<cnt;i++)
		printf(" %d",res[i]);
	puts("");
	return 0;
}
/*
7
1 2
2 5
2 3
3 4
3 6
6 7

*/


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值