您的位置:首页 > 其它

POJ 1848 Tree

2012-02-14 18:53 239 查看
Tree

Time Limit: 1000MSMemory Limit: 30000K
Total Submissions: 2564Accepted: 859
Description

Consider a tree with N vertices, numbered from 1 to N. Add, if it is possible, a minimum number of edges thus every vertex belongs to exactly one cycle.

Input

The input has the following structure:

N

x(1) y(1)

x(2) y(2)

...

x(N-1) y(n-1)

N (3 <= N <=100) is the number of vertices. x(i) and y(i) (x(i), y(i) are integers, 1 <= x(i), y(i) <= N) represent the two vertices connected by the i-th edge.

Output

The output will contain the value -1 if the problem doesn't have a solution, otherwise an integer, representing the number of added edges.

Sample Input
7
1 2
1 3
3 5
3 4
5 6
5 7


Sample Output
2


Source

Romania OI 2002

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define INF 100

#define MAXN 110
#define MAXE 220
struct LEdge{
int ed, next;
}edge[MAXE];
int head[MAXN], nEdge;

void init(){
nEdge = 0;
memset(head, 0xff, sizeof(head));
}

void addEdge(int i, int j){
edge[nEdge].ed = j;
edge[nEdge].next = head[i];
head[i] = nEdge++;
}

int f[MAXN][3];

int imin(int a, int b){
if (a < 0) return b;
if (b < 0) return a;
return a < b ? a : b;
}

int dfs(int pre, int cur){
int i, j, k, p, q, sum;
sum = 0;
for (i = head[cur]; i != -1; i = edge[i].next){
k = edge[i].ed;
if (k == pre) continue;
if (!dfs(cur, k)) return 0;
sum += f[k][0];
}
f[cur][0] = f[cur][1] = f[cur][2] = INF;
f[cur][1] = sum;
for (i = head[cur]; i != -1; i = edge[i].next){
p = edge[i].ed;
if (p == pre) continue;
f[cur][0] = imin(f[cur][0], f[p][2] - f[p][0] + sum + 1);
f[cur][2] = imin(f[cur][2], f[p][2] - f[p][0] + sum);
f[cur][2] = imin(f[cur][2], f[p][1] - f[p][0] + sum);
for (j = edge[i].next; j != -1; j = edge[j].next){
q = edge[j].ed;
if (q == pre) continue;
f[cur][0] = imin(f[cur][0], f[p][1] - f[p][0] + f[q][1] - f[q][0] + sum + 1);
f[cur][0] = imin(f[cur][0], f[p][2] - f[p][0] + f[q][1] - f[q][0] + sum + 1);
f[cur][0] = imin(f[cur][0], f[p][1] - f[p][0] + f[q][2] - f[q][0] + sum + 1);
f[cur][0] = imin(f[cur][0], f[p][2] - f[p][0] + f[q][2] - f[q][0] + sum + 1);
}
}
//	printf("cur = %d, f[0] = %d, f[1] = %d, f[2] = %d, t = %d, p = %d, q = %d, r = %d\n", cur, f[cur][0], f[cur][1], f[cur][2], t, p, q, r);
if (f[cur][0] >= INF && f[cur][1] >= INF && f[cur][2] >= INF)
return 0;
return 1;
}

int main(){
int i, j, k, n;
while(scanf("%d", &n) != EOF){
init();
for (k = 1; k < n; k++){
scanf("%d%d", &i, &j);
addEdge(i, j);
addEdge(j, i);
}
if (!dfs(0, 1) || f[1][0] >= INF) f[1][0] = -1;
printf("%d\n", f[1][0]);
}
return 0;
}

/*
f[i][0] i及其以下已成环
f[i][1] 仅i没成环
f[i][2] i带着一个长至少为2的链

f[i][0] = min(
f[p][1] + f[q][1] + sum(f[其他][0]) + 1,
f[p][2] + f[q][1] + sum(f[其他][0]) + 1,
f[p][1] + f[q][2] + sum(f[其他][0]) + 1,
f[p][2] + f[q][2] + sum(f[其他][0]) + 1,
f[p][2] + sum(f[其他][0]) + 1)
f[i][1] = sum(f[其他][0])
f[i][2] = min(
f[p][2] + sum(f[其他][0]),
f[p][1] + sum(f[其他][0]))

开始无效值是-1,虽然做了好多好多特判
例如,有的子树本身无法全部成环,这样的点如果有一个,
可以通过和当前点组成环,或者和其他链组成环,或者作为当前点的链
如果有两个,则必须把他俩连一块
如果多于两个,说明无解
但是都WA掉了
后来看了网上的,没那么多特判,枚举起来也特暴力
初值设的INF,于是改成比较暴力的二重循环,而不是一重去找,
写的简单了,也就过了
经验: 尽量简洁,卡住了就释放些暴力
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: