Godfather poj-3107
题目大意:求树的重心裸题。
注释:n<=50000.
想法:我们尝试用树形dp求树的重心,关于树的重心的定义在题目中给的很明确。关于这道题,我们邻接矩阵存不下,用链式前向星存边,然后对于任选节点遍历,然后在回溯是进行最大值的最小值更新,之后就是一点显然的结论——树最多只有两个重心,而且这两个加点必须连边。
最后,附上丑陋的代码... ...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n; int k; int nxt[100050]; int to[100050]; int head[100050]; int g=0; int sum[100050]; int maxj[100050]; int minn=0x7f7f7f7f; int a,b; void dfs(int d,int fa) { for(int i=head[d];i!=0;i=to[i]) { int z=nxt[i]; if(z!=fa) { dfs(z,d); } } maxj[d]=max(maxj[d],n-sum[d]-1); minn=min(minn,maxj[d]); sum[d]+=1; sum[fa]+=sum[d]; maxj[fa]=max(sum[d],maxj[fa]); return; } int main() { scanf("%d",&n); for(int i=1;i<n;++i) { scanf("%d%d",&a,&b); nxt[++g]=b; to[g]=head[a]; head[a]=g; nxt[++g]=a; to[g]=head[b]; head[b]=g; } dfs(1,0); for(int i=1;i<=n;++i) { if(maxj[i]==minn) { printf("%d ",i); } } puts(""); return 0; }
小结:第二道树形dp,upupup