zoukankan      html  css  js  c++  java
  • 「日常训练」Balancing Act(POJ-1655)

    题意与分析

    树的重心板子题。
    值得考虑的是,重心究竟有哪些优秀的性质?
    这里是一些网上能看到的性质:

    1. (判定性质)找到一个点,其所有的子树中最大的子树节点数最少(子树可以“倒着看”),那么这个点就是这棵树的重心。
    2. 以这个点为根,那么所有的子树(不算整个树自身)的大小都不超过整个树大小的一半。
    3. 树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么他们的距离和一样。
    4. 把两个树通过一条边相连得到一个新的树,那么新的树的重心在连接原来两个树的重心的路径上。
    5. 把一个树添加或删除一个叶子,那么它的重心最多只移动一条边的距离。

    利用判定性质能够在一次dfs内完成树的重心的判断。定义(dp[i])是第i个节点所拥有的子树的节点的最小值,更新即可。具体看代码。
    相关题目见之后的题解。

    代码

    #include <iostream>
    #include <cstring>
    #include <utility>
    #include <vector>
    
    #define INF 0x3f3f3f3f
    #define PB push_back
    #define MP make_pair
    #define fi first
    #define se second
    #define rep(i,a,b) for(repType i=(a); i<=(b); ++i)
    #define per(i,a,b) for(repType i=(a); i>=(b); --i)
    #define ZERO(x) memset(x, 0, sizeof(x))
    #define MS(x,y) memset(x, y, sizeof(x))
    #define ALL(x) (x).begin(), (x).end()
    
    #define QUICKIO                  
        ios::sync_with_stdio(false); 
        cin.tie(0);                  
        cout.tie(0);
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
    
    using namespace std;
    typedef int repType;
    
    const int MAXN=20005;
    vector<int> G[MAXN];
    int cnt[MAXN],dp[MAXN];
    int n;
    int dfs(int x)
    {
        if(cnt[x]!=0) return 0;
        cnt[x]=1;
        rep(i,0,int(G[x].size())-1)
        {
            cnt[x]+=dfs(G[x][i]);
            dp[x]=max(dp[x],cnt[G[x][i]]);
        }
        dp[x]=max(dp[x],n-cnt[x]);
        return cnt[x];
    }
    
    int
    main()
    {
        int T; cin>>T;
        while(T--)
        {
            cin>>n;
            rep(i,1,n) G[i].clear();
            rep(i,1,n-1)
            {
                int u,v; cin>>u>>v;
                G[u].PB(v);
                G[v].PB(u);
            }
            MS(cnt,0);
            MS(dp,-1);
            rep(i,1,n)
                if(!cnt[i]) dfs(i);
            int ans=INF,pos=0;
            rep(i,1,n)
                if(ans>dp[i])
                    ans=dp[pos=i];
            cout<<pos<<" "<<ans<<endl;
        }
        return 0;
    }
    
    如非注明,原创内容遵循GFDLv1.3发布;其中的代码遵循GPLv3发布。
  • 相关阅读:
    Android5.0录屏方案
    Android点阵屏效果的控件
    Android绘制View相关的几个问题
    AndroidStudio导入第三方开源库
    第六百二十三天 how can I坚持
    第六百二十二天 how can I 坚持
    第六百二十一天 how can I 坚持
    第六百二十天 how can I 坚持
    第六百一十九天 how can I 坚持
    第六百一十八天 how can I 坚持
  • 原文地址:https://www.cnblogs.com/samhx/p/poj-1655.html
Copyright © 2011-2022 走看看