树的重心算法
就是用DFS实现一个树形DP。在DFS的过程中枚举每一个结点的每一个子树,然后比较求出每一个结点的最大子树(不要忘了它的父亲也是它的一个子树,它父亲所在的子树的值由总节点权重和和该点为根的子树的值的差),然后取拥有最大子树最小的就是树的重心。
代码
POJ1655 AC确认,该题裸板,就是多了一个出现多个重心时的取舍
#include <iostream>
#include <vector>
#include <cstring>
/*
* 本版子是潘骏同志瞎写的树的重心板子
*/
using namespace std;
struct edge
{
int nxt;
int to;
edge(int t,int n):to(t),nxt(n){
}
};
vector<edge> edges;
int egs[20005];
void addedge(int f,int t)
{
edge temp=edge(t,egs[f]);//POJ不支持C++11
edges.push_back(temp);
egs[f]=edges.size()-1;
}
int center;
int centerv;
int sizer[20005];
int n;
void dfs(int now,int fa)
{
int maxson=0;
sizer[now]=1;
for(int i=egs[now];i!=-1;i=edges[i].nxt){
int nxter=edges[i].to;
if(nxter!=fa){
dfs(nxter,now);
sizer[now]+=sizer[nxter];//更新自己的size值,给爸爸用的
maxson=max(maxson,sizer[nxter]);
}
}
maxson=max(maxson,n-sizer[now]);//以爸爸为根结点的子树是总权值(这里大家点权都是1)-自己为根子树
if(maxson<centerv)
{
centerv=maxson;//更新重心
center=now;
}
else if(maxson==centerv && now<center)
{
center=now;
}
}
int main() {
int t;
cin>>t;
while(t--)
{
cin>>n;
memset(egs,-1,sizeof egs);
edges.clear();
for(int i=0;i<n-1;i++)
{
int a,b;
cin>>a>>b;
addedge(a,b);
addedge(b,a);
}
center=0x3f3f3f3f;
centerv=0x3f3f3f3f;//要求最小值所以初始化无穷大。
dfs(1,0);
cout<<center<<" "<<centerv<<endl;
}
return 0;
}
参考了以下博主,在此表示感谢: