1001 小G有一个大树 dfs 树形DP

链接:https://ac.nowcoder.com/acm/contest/25022/1001
来源:牛客网

题目描述

小G想要把自己家院子里的橘子树搬到家门口(QAQ。。就当小G是大力水手吧)
可是小G是个平衡性灰常灰常差的人,他想找到一个这个橘子树的平衡点。
怎么描述这棵树呢。。。就把它看成由一个个节点构成的树吧。结点数就
代表树重。

输入描述:

多组数据输入输出,
第一行包含一个整数n(3<=n<=1000)代表树的结点的个数
以下n-1行描述(1-n)节点间的连接关系。

输出描述:

输出两个个整数 x,num 分别代表树的平衡点,和删除平衡点后最大子树的结点数(如果结点数相同输出编号小的)。
示例1

输入

复制
3
1 2
1 3

输出

复制
1 1

 

分析

平衡点:删除某个节点后,形成的多颗树的最大节点数最小。

深度优先搜索一下,算一下每个节点的子树大小,取最大值,然后ans取每个节点的最小值,那个最小值所在的点就是平衡点。

//-------------------------代码----------------------------

//#define int ll
const int N = 1e5+10;
int n,m;
int ans = inf;
int sz[N],p,cnt = 0;

void dfs(int u,int fa,V<int> g[]) {
    int res = 0;cnt ++ ;
//     if(cnt == 50) {bd;gg;}
    for(int i = 0;i<g[u].size();i ++ ) {
        if(g[u][i] == fa) continue;
        dfs(g[u][i],u,g);
        sz[u] += sz[g[u][i]];
        res = max(sz[g[u][i]],res);
    }
    sz[u] += 1;
    res = max(res,n-sz[u]);
    if(res < ans) {
        ans = res;
        p = u;
    }
}

void solve() {
    ans = inf;
    ms(sz,0);
    cin>>n;
    V<int> g[n+1];
    V<bool > vis(n+1);
    fo(i,1,n-1) {
        int a,b;cin>>a>>b;
        g[a].pb(b);
        vis[b] = 1;
    }
    int root;
    fo(i,1,n) {
        if(vis[i] == 0) {
            root = i;
            break;
        }
    }
    dfs(root,-1,g);
    cout<<p<<' ' << ans<<endl;
}

signed main(){
    clapping();TLE;
    
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

posted @ 2022-08-01 13:57  er007  阅读(30)  评论(0编辑  收藏  举报