您的位置:首页 > 其它

POJ 1655 - DP 树的重心,经典 #P

2013-06-16 09:40 387 查看
POJ 1655 - DP 树的重心,经典 #P

题意:求树的重心。
树的重心:删去重心后,生成的多棵树尽可能平衡。
重心的意义,在对树进行分治的时候可以避免N^2的极端复杂度(从退化链的一端出发),保证NlogN的复杂度。

解法:
一开始想到的是模仿求树的直径那样子去Dp,两次DFS。
son[i] - 结点i的儿子结点数目
第一遍求出son;
h[i] - 结点i向上的结点数目
h[i] = h[k] + son[k] - son[i] - 1;
blance = max(son[j] , h[i])
第二遍求出h,和blance;

后来去看题解,才发现有更简单的方法。
应用一个性质,h[i] = n - son[i] -1;
blance = max(son[j] , n - son[i] -1);
这样只需要一次DFS。

#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <vector>
#define OP(s) cout<<#s<<"="<<s<<" ";
#define PP(s) cout<<#s<<"="<<s<<endl;
using namespace std;
int n;
vector <int> adj[20010];

int son[20010];
bool vd[20010];
int ans,asize = 1<<29;
void DFS(int s)
{
vd[s] = 1;
son[s] = 0;
int blance = 0;
int size = adj[s].size();
for (int j = 0;j < size;j++)
{
int u = adj[s][j];
if (vd[u]) continue;
DFS(u);
son[s] += son[u]+1;
blance = max(blance,son[u]+1);
}
blance = max(blance,n - son[s] - 1);
if (blance < asize || blance == asize && s < ans)
ans = s,asize = blance;
}

int main()
{
//    freopen("test.txt","r",stdin);
int T;
cin>>T;
while(T--)
{
cin>>n;
for (int i = 1;i <= n;i++) adj[i].clear();
for (int i = 1;i <= n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
adj[u].push_back(v);
adj[v].push_back(u);
}

memset(vd,0,sizeof(vd));
asize = 1<<29;
DFS(1);
cout<<ans<<" "<<asize<<endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: