您的位置:首页 > 编程语言 > Go语言

POJ 3107 - Godfather

2014-05-01 01:29 363 查看
本题与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('\n');
return 0;
}


3107Accepted4104K532MSG++1249B2014-05-01 01:22:57
5/3更新 求树的重心模板:

#include <cstdio>
#include <cstring>
using namespace std;

#define FOR(p,i,s,t) for(__typeof(p) i=s; i<t; ++i)
#define REP(t,i,n)    FOR(t,i,0,n)

#define ECH(it, A) for (__typeof(A.begin()) it=A.begin(); it != A.end(); ++it)
#define RST(x,y) memset(x, y, sizeof(x))
#define RST0(x)    RST(x,0)

typedef int Vt, Lt;
const __typeof(Vt) MAXV = 50005;

#define MAXE    ((MAXV<<1) - 2)

Vt Vefw[MAXE], Veh[MAXV], eptr = 0;
struct Vedge {
Vt t;
Lt l;
Vedge() {}
Vedge(Vt _t): t(_t), l(1) {}
Vedge(Vt _t, Lt _l): t(_t), l(_l) {}
void attach(Vt s) {
extern Vedge Vs[];
memcpy(Vs + eptr, this, sizeof(Vedge));
Vefw[eptr] = Veh[s]; Veh[s] = ++eptr;
}
};
#define addedge(s,t,l) ({Vedge e(t,l); e.attach(s);})
Vedge Vs[MAXE];
Vt gcoref_tot;
char gc_8[MAXV];
Vt gc_maxk[MAXV], gc_sumn[MAXV];

int gc_root;

void gcoref(Vt i)
{
char _gc8;
if (!(_gc8 = gc_8[i])) gc_8[i] = -1;    // 遍历去环
Vt sumn = 1, maxk = 0;
for(Vt e = Veh[i]; e; e = Vefw[e]) {
Vt t = Vs[--e].t;
if (!gc_8[t]) {
gcoref(t);
sumn += gc_sumn[t];
if (maxk < gc_sumn[t])
maxk = gc_sumn[t];
}
}
gc_8[i] = _gc8;                // gc_8还有其他用途
if (gcoref_tot - sumn > maxk) maxk = gcoref_tot - sumn;
gc_sumn[i] = sumn, gc_maxk[i] = maxk;
if (gc_maxk[gc_root] > maxk) gc_root = i;
}

inline Vt gcore(Vt root)
{
gc_maxk[gc_root = root] = gcoref_tot;
gcoref(root);
return gc_root;
}

int N;

// 本模板使用方式:  gcoref_tot = 实际节点数
// gc_8 != 0, 该节点被剪掉(忽略),可以用来存储其他信息
// addedge加边(注意针对 无根树 要加双向),gcore返回重心节点
// gc_maxk里面存储所有节点的最大真子树的节点数.

int main(void)
{
//    freopen("poj3107.txt", "r", stdin);
scanf("%d", &N);
Vt root = 0;
REP(int, i, N-1) {
Lt l;
Vt s,t;
scanf("%d%d", &s, &t); --s, --t;
addedge(s,t,1), addedge(t,s,1);
if (root == t) root = s;
}
gcoref_tot = N;
root = gcore(root);
Vt i;
for(i = 0; i < N; ++i)
if (gc_maxk[i] == gc_maxk[root]) {
printf("%d", ++i);
break;
}
for(; i<N; ++i)
if (gc_maxk[i] == gc_maxk[root])
printf(" %d", i+1);
putchar('\n');
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: