POJ3107-树的重心&树形DP-Godfather

来源:互联网 发布:c语言播放音乐函数 编辑:程序博客网 时间:2024/05/17 22:36

https://vjudge.net/problem/POJ-3107
寻找一个点,删除之后,他的最大子树最小。其实就是树的重心。
如果有很多相同的,就按大小输出。
简单的树形DP应用。。求完所有树的重心之后处理,或者在dfs的过程中也能进行处理,都是可以的。
但那个要nlogn的排序,因为输出要顺序qwq

#include <iostream>#include <stdio.h>#include <string.h>#include <string>#include <stack>#include <queue>#include <map>#include <set>#include <vector>#include <math.h>#include <bitset>#include <list>#include <algorithm>#include <climits>using namespace std;/*树的重心,就是刨掉一个点之后,最大子树最小。苟神说,树形dp可以很方便的求数的重心。*/const int maxn=2e5+20;struct Node{       int to;       int next;}node[maxn];int len;int head[maxn];void add(int a,int b){     node[len].to=b;     node[len].next=head[a];     head[a]=len++;}int m;bool vis[maxn];int c_tre[maxn];void Init(){len=0;memset(head,-1,sizeof(head));memset(vis,false,sizeof(vis));memset(c_tre,0,sizeof(c_tre));}int dfs(int x){    c_tre[x]=0;    vis[x]=true;    int all=0;    for(int i=head[x];i!=-1;i=node[i].next)   {    int to=node[i].to;        if(vis[to]) continue;        int ccl=dfs(to);        c_tre[x]=max(c_tre[x],ccl+1);        all+=(ccl+1);   }   c_tre[x]=max(c_tre[x],m-all-1);   return all;}int main(){   int t;    int a,b;     while(~scanf("%d",&m)){          Init();          for(int i=0;i<m-1;i++){              scanf("%d%d",&a,&b);              add(b,a);              add(a,b);          }          dfs(1);          vector<int>c;          int min1=1e8;          for(int i=1;i<=m;i++){            if(min1>c_tre[i]){                min1=c_tre[i];                c.clear();                c.push_back(i);            }            else if(min1==c_tre[i])                c.push_back(i);            }            vector<int>::iterator it;            int tim=0;            for(it=c.begin();it!=c.end();it++){                if(tim!=0)                cout<<" "<<*it;                else                cout<<*it;                tim++;            }    }    return 0;}