poj 1655 树重心

解题思路: 

  树重心,将其与其最大子树连接的边,删除后,划分出的两个子树节点数量最大的中的最小.

  题目其实是树的重心的一点变异。  树的重心是 树中所有节点的字节点数量最大中的最小的节点

  O(n) 求出每个点的的子节点的最大值以及其字节点总个数,然后在线性比较下就可以求出重心了,

  此题要注意, 这里要求的是 所有的(节点的子节点数量的最大值)中最小的.   

解题代码:

  

View Code
#include<stdio.h>

#include<string.h>

#include<stdlib.h>

using namespace std;

#define MAX(a,b) (a)>(b)?(a):(b)

#define MIN(a,b) (a)<(b)?(a):(b)

const int N = 20010;



int M[N], n;

int head[N], idx;

struct node{

    int max, sum;

}D[N];

struct Edge{

    int v, next;

}edge[N<<2];



void AddEdge(int a, int b)

{

    edge[idx].v = b; edge[idx].next = head[a]; head[a] = idx++;

    edge[idx].v = a; edge[idx].next = head[b]; head[b] = idx++;

}

void input()

{

    int a, b;    

    scanf("%d", &n);

    memset( head, 0xff, sizeof(head));

    idx = 0;    

    for(int i = 0; i < n-1; i++)

    {

        scanf("%d%d", &a,&b );

        AddEdge(a, b);

    }

}

int dfs( int u, int pre )

{

    D[u].sum = 1; D[u].max = 0;

    for(int i = head[u]; ~i; i = edge[i].next )

    {

        if( edge[i].v != pre )

        {

            int t = dfs( edge[i].v, u );

            D[u].sum += t;

            D[u].max = MAX( D[u].max, t );

        }

    }

    return D[u].sum;

}

void solve()

{

    dfs( 1, 0 );

    int ans = 0x3fffffff, rt;    

    for(int i = 1; i <= n; i++)

    {

        D[i].max = MAX( D[i].max, n-D[i].sum );    

        if( ans > D[i].max )

        {

            rt = i; ans = D[i].max;    

        }

    }

    printf("%d %d\n", rt, ans ); 

}

int main()

{

    int T; 

    scanf("%d", &T);

    while( T-- )

    {

        input();

        solve();

    }

    return 0;

}

 

你可能感兴趣的:(poj)