1. 程式人生 > >poj1655 Balancing Act (dp? dfs?)

poj1655 Balancing Act (dp? dfs?)

lan from bsp 樹的重心 case test case amp mit esp

Balancing Act

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 14247 Accepted: 6026

Description

Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the largest tree in the forest T created by deleting that node from T.
For example, consider the tree:
技術分享

Deleting node 4 yields two trees whose member nodes are {5} and {1,2,3,6,7}. The larger of these two trees has five nodes, thus the balance of node 4 is five. Deleting node 1 yields a forest of three trees of equal size: {2,6}, {3,7}, and {4,5}. Each of these trees has two nodes, so the balance of node 1 is two.

For each input tree, calculate the node that has the minimum balance. If multiple nodes have equal balance, output the one with the lowest number.

Input

The first line of input contains a single integer t (1 <= t <= 20), the number of test cases. The first line of each test case contains an integer N (1 <= N <= 20,000), the number of congruence. The next N-1 lines each contains two space-separated node numbers that are the endpoints of an edge in the tree. No edge will be listed twice, and all edges will be listed.

Output

For each test case, print a line containing two integers, the number of the node with minimum balance and the balance of that node.

Sample Input

1
7
2 6
1 2
1 4
4 5
3 7
3 1

Sample Output

1 2

題意:

找樹的重心,即:
定義1:找到一個點,其所有的子樹中最大的子樹節點數最少,那麽這個點就是這棵樹的重心。
定義2:以這個點為根,那麽所有的子樹(不算整個樹自身)的大小都不超過整個樹大小的一半。
性質1:樹中所有點到某個點的距離和中,到重心的距離和是最小的;如果有兩個重心,那麽他們的距離和一樣。
性質2:把兩個樹通過一條邊相連得到一個新的樹,那麽新的樹的重心在連接原來兩個樹的重心的路徑上。
性質3:把一個樹添加或刪除一個葉子,那麽它的重心最多只移動一條邊的距離。

思路:

選取任意節點為根節點,dfs求當前節點所代表的子樹的節點總數(包含自己記為sum)和該節點的所有子樹中節點數最大值(記為ave)。則依據題意,刪除當前節點後的平衡值為

max(n-sum,ave);找到最小值輸出。

看到別人說是dp,可能我不會dp。

代碼:

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int maxn = 2e4+4, INF = 0x3f3f3f3f;

vector<int> grap[maxn];
int vis[maxn], sum[maxn], ave[maxn];
int t, n;

int dfs(int x)
{
    int res=1;
    for(int i=0; i<grap[x].size(); ++i)
    {
        int xx=grap[x][i];
        if(vis[xx]) continue;
        vis[xx]=1;
        int kk=dfs(xx);
        ave[x]=max(ave[x], kk);
        res+=kk;
        vis[xx]=0;
    }
    sum[x]=res;
    ave[x]=max(ave[x], n-sum[x]);
    return res;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1; i<=n; ++i)
        {
            grap[i].clear();
            vis[i]=0;
            sum[i]=0;
            ave[i]=0;
        }
        for(int i=2; i<=n; ++i)
        {
            int u, v;
            cin>>u>>v;
            grap[u].push_back(v);
            grap[v].push_back(u);
        }
        vis[1]=1;
        dfs(1);
        int ans=INF, v=0;
        for(int i=1; i<=n; ++i)
            if(ans>ave[i])
                ans=ave[i], v=i;
        cout<<v<<" "<<ans<<endl;
    }
    return 0;
}

poj1655 Balancing Act (dp? dfs?)