思路1:
统计每个点的子树有多少个节点,同时记录子节点的子树中,有节点数量最多的子树,dp即可
dp[i]表示以节点i为根的子树有多少节点,f[i]表示以i为根的子树中,最多的节点分支数
思路2:之前写过一次,现在学点分治又重新写了一次,现在写的比以前快了很多,树的重心定义为:以它为根结点,它的子树的节点数目最大值最小。
利用size[u]记录以它为根的子树的节点数量,dp[u]记录子树的最大节点数量,dfs一遍就行。
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<map>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#include<set>
#include<sstream>
#include<cstdio>
#include<unordered_map>
#include<unordered_set>
#include<cmath>
#include<climits>
using namespace std;
const int maxn=2e6+9;
int head[maxn];
int num;
int n,m;
int dp[maxn];
int f[maxn];
struct Edge
{
int u,v,w,next;
}edge[maxn];
void addEdge(int u,int v,int w)
{
edge[num].u=u;
edge[num].v=v;
edge[num].w=w;
edge[num].next=head[u];
head[u]=num++;
}
void init()
{
memset(head,-1,sizeof(head));
memset(dp,0,sizeof(dp));
memset(f,0,sizeof(f));
num=0;
}
void dfs(int u,int pre)
{
dp[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==pre) continue;
dfs(v,u);
dp[u]+=dp[v];
f[u]=max(f[u],dp[v]);
}
}
int main(int argc, char const *argv[])
{
int T;
cin>>T;
while(T--)
{
init();
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addEdge(x,y,0);
addEdge(y,x,0);
}
dfs(1,-1);
int ans=1e9+9;
int k=0;
for(int i=1;i<=n;i++)
{
int tmp;
tmp=max(n-dp[i],f[i]);
if(ans>tmp)
{
k=i;
ans=tmp;
}
}
printf("%d %d\n",k,ans);
}
return 0;
}
代码2:
#include<iostream>
#include<map>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#include<set>
#include<sstream>
#include<cstdio>
#include<cmath>
#include<climits>
using namespace std;
const int maxn=2e6+9;
int head[maxn];
int num;
int n,m;
int dp[maxn];
int size[maxn];
int Focus,M;
struct Edge
{
int u,v,w,next;
}edge[maxn];
void addEdge(int u,int v,int w)
{
edge[num].u=u;
edge[num].v=v;
edge[num].w=w;
edge[num].next=head[u];
head[u]=num++;
}
void init()
{
memset(head,-1,sizeof(head));
num=0;
}
void getFocus(int u,int pre)
{
size[u]=1;
dp[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==pre) continue;
getFocus(v,u);
size[u]+=size[v];
dp[u]=max(dp[u],size[v]);
}
dp[u]=max(dp[u],n-size[u]);
if(M>dp[u])
{
M=dp[u];
Focus=u;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T;
cin>>T;
while(T--)
{
init();
scanf("%d",&n);
for(int i=1,u,v;i<n;i++)
{
scanf("%d%d",&u,&v);
addEdge(u,v,0);
addEdge(v,u,0);
}
M=1e9;
getFocus(1,0);
printf("%d %d\n",Focus,M);
}
return 0;
}