poj 1655 Balancing Act 【树的重心】

刘汝佳白书上思路
树的重心(质心):使得最大子树的结点数最小化

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const int maxn=21000;
vector<int>G[maxn];
int vis[maxn];
int son[maxn];
int ans,arise;;
int n;

void init(int n){
    for(int i=1;i<=n;i++)
        G[i].clear();
    mem0(vis);
}

void dfs(int s){
    vis[s]=1;
    son[s]=0;
    int balance=0;
    for(int i=0;i<G[s].size();i++){
        int x=G[s][i];
        if(vis[x])
            continue;
        dfs(x);
        son[s]+=son[x]+1;
        balance=max(balance,son[x]+1);
    }
    balance=max(balance,n-son[s]-1);
    if(balance<arise||(balance==arise&&s<ans)){
        arise=balance;
        ans=s;
    }
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int x,y;
        scanf("%d",&n);
        init(n);
        for(int i=0;i<n-1;i++){
            scanf("%d%d",&x,&y);
            G[x].push_back(y);
            G[y].push_back(x);
        }
        ans=1,arise=INF;
        dfs(1);
        printf("%d %d\n",ans,arise);
    }
    return 0;
}

你可能感兴趣的:(数据结构,刘汝佳)