您的位置:首页 > 其它

poj 1655 Balancing Act 树状dp

2015-03-28 15:08 267 查看
//poj1655树状dp
//求一个数的重心
// dfs找到节点v的各个子树的节点数
// 取最大值设为num[v],而v节点以上的子树的节点数
// 为总数-num[v]-1(包括v节点本身)设为t
// dp[v] = max (num[v],t);
// 则最终的结果为min(dp[i])对应的i和dp[i];
// 对于dp渣渣的我,真的不简单,哎,继续练喽
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 20080;
struct Edge{
	int v;
	int next;
}edges[maxn<<1];
bool vis[maxn];
int adj[maxn];
int dp[maxn];
int nu[maxn];
int n;
int num;
void addEdge(int u,int v){
	edges[num].v = v;
	edges[num].next = adj[u];
	adj[u] = num++;
	edges[num].v = u;
	edges[num].next = adj[v];
	adj[v] = num++;
}

void init(){
	scanf("%d",&n);
	num=0;
	memset(adj,-1,sizeof(adj));
	memset(dp,0,sizeof(dp));
	memset(vis,0,sizeof(vis));
	memset(nu,0,sizeof(nu));
	for (int i=0;i<n-1;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		addEdge(a,b);
	}
}

int dfs(int u){
	int sum=0,ans=0;
	vis[u] = true;
	for (int i=adj[u];i!=-1;i = edges[i].next){
		int v = edges[i].v;
		if (!vis[v]){
			int t = dfs(v);
			sum +=t;
			ans = max (ans,t);
		}
	}
	nu[u] = sum+1;
	int t = n-nu[u];
	dp[u]=max(t,ans);
	return nu[u];

}

void solve(int &ans,int &index){
	dfs(1);
	for (int i=1;i<=n;i++)
		if (ans>dp[i]){
			ans=dp[i];
			index=i;
		}
	printf("%d %d\n",index,ans);
}

// void print(int &ans){

// }

int main(){
	int t;
	freopen("G:\\Code\\1.txt","r",stdin);
	scanf("%d",&t);
	while(t--){
		//printf("111\n");
		int ans=0x7f7f7f7f;
		int index=0;
		init();
		solve(ans,index);
		//print(ans);
	}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: