POJ 3107

本题与POJ 1655的区别是要把所有重心的点按顺序输出出来。

// poj3107 Godfather
#include <cstdio>
#include <cstring>
#define NDEBUG


#define MAXN    50005

using namespace std;

int N;
int edgefw[MAXN*2], edge[MAXN*2], head[MAXN], eptr;

#define EI(j, k)    ({ 
    edge[eptr] = k, edgefw[eptr] = head[j];    
    head[j] = eptr++;    
})

int dp[MAXN], dp2[MAXN];
char vis[MAXN];

void dfs(int i)
{
    vis[i] = 1;
    int p, maxk = 0, sumn = 1;
    for(p = head[i]; p>=0; p = edgefw[p]) {
        int t = edge[p];
        if (!vis[t]) {
            if (!dp2[t]) dfs(t);
            sumn += dp2[t];
            if (maxk < dp2[t])
                    maxk = dp2[t];
        }
    }
    if (sumn != N && N - sumn > maxk) maxk = N - sumn;
    dp[i] = maxk, dp2[i] = sumn;
}

int main(void)
{
    #ifndef NDEBUG
    freopen("poj3107.in", "r", stdin);
    #endif // NDEBUG
    scanf("%d", &N);
    memset(head, -1, sizeof(int) * N), eptr = 0;
    int i, j, root;
    root = 0;
    for(i=1; i<N; ++i) {
        int k;
        scanf("%d%d", &j, &k);
        --j,--k; EI(j, k), EI(k, j);
        if (root == k) root = j;
    }
    dfs(root);
    j = 0;
    for(i = 1; i < N; ++i)
        if (dp[i] < dp[j])
            j = i;
    root = 0;
    for(i = 0; i < N; ++i)
        if (dp[i] == dp[j]) {
            printf("%d", ++i);
            break;
        }
    for(; i<N; ++i)
        if (dp[i] == dp[j])
            printf(" %d", i+1);
    putchar('
');
    return 0;
}
3107 Accepted 4104K 532MS G++ 1249B 2014-05-01 01:22:57

5/3更新 求树的重心模板:

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 
 6 #define FOR(p,i,s,t) for(__typeof(p) i=s; i<t; ++i)
 7 #define REP(t,i,n)    FOR(t,i,0,n)
 8 
 9 #define ECH(it, A) for (__typeof(A.begin()) it=A.begin(); it != A.end(); ++it)
10 #define RST(x,y) memset(x, y, sizeof(x))
11 #define RST0(x)    RST(x,0)
12 
13 typedef int Vt, Lt;
14 const __typeof(Vt) MAXV = 50005;
15 
16 #define MAXE    ((MAXV<<1) - 2)
17 
18 Vt Vefw[MAXE], Veh[MAXV], eptr = 0;
19 struct Vedge {
20     Vt t;
21     Lt l;
22     Vedge() {}
23     Vedge(Vt _t): t(_t), l(1) {}
24     Vedge(Vt _t, Lt _l): t(_t), l(_l) {}
25     void attach(Vt s) {
26         extern Vedge Vs[];
27         memcpy(Vs + eptr, this, sizeof(Vedge));
28         Vefw[eptr] = Veh[s]; Veh[s] = ++eptr;
29     }
30 };
31 #define addedge(s,t,l) ({Vedge e(t,l); e.attach(s);})
32 Vedge Vs[MAXE];
33 Vt gcoref_tot;
34 char gc_8[MAXV];
35 Vt gc_maxk[MAXV], gc_sumn[MAXV];
36 
37 int gc_root;
38 
39 void gcoref(Vt i)
40 {
41     char _gc8;
42     if (!(_gc8 = gc_8[i])) gc_8[i] = -1;    // 遍历去环
43     Vt sumn = 1, maxk = 0;
44     for(Vt e = Veh[i]; e; e = Vefw[e]) {
45         Vt t = Vs[--e].t;
46         if (!gc_8[t]) {
47             gcoref(t);
48             sumn += gc_sumn[t];
49             if (maxk < gc_sumn[t])
50                 maxk = gc_sumn[t];
51         }
52     }
53     gc_8[i] = _gc8;                // gc_8还有其他用途
54     if (gcoref_tot - sumn > maxk) maxk = gcoref_tot - sumn;
55     gc_sumn[i] = sumn, gc_maxk[i] = maxk;
56     if (gc_maxk[gc_root] > maxk) gc_root = i;
57 }
58 
59 inline Vt gcore(Vt root)
60 {
61     gc_maxk[gc_root = root] = gcoref_tot;
62     gcoref(root);
63     return gc_root;
64 }
65 
66 int N;
67 
68 // 本模板使用方式:  gcoref_tot = 实际节点数
69 // gc_8 != 0, 该节点被剪掉(忽略),可以用来存储其他信息
70 // addedge加边(注意针对 无根树 要加双向),gcore返回重心节点
71 // gc_maxk里面存储所有节点的最大真子树的节点数.
72 
73 int main(void)
74 {
75 //    freopen("poj3107.txt", "r", stdin);
76     scanf("%d", &N);
77     Vt root = 0;
78     REP(int, i, N-1) {
79         Lt l;
80         Vt s,t;
81         scanf("%d%d", &s, &t); --s, --t;
82         addedge(s,t,1), addedge(t,s,1);
83         if (root == t) root = s;
84     }
85     gcoref_tot = N;
86     root = gcore(root);
87     Vt i;
88     for(i = 0; i < N; ++i)
89         if (gc_maxk[i] == gc_maxk[root]) {
90             printf("%d", ++i);
91             break;
92         }
93     for(; i<N; ++i)
94         if (gc_maxk[i] == gc_maxk[root])
95             printf(" %d", i+1);
96     putchar('
');
97     return 0;
98 }
原文地址:https://www.cnblogs.com/e0e1e/p/poj_3107.html