题目链接:http://poj.org/problem?id=1308
大意就是给一些点的指向关系,最后问能否组成一棵树。
用并查集写了,每次给的两个点不在相同集合,就合并,合并一次相当于多增加了一条边,所以在合并的时候记录一下边数,如果合并过程中出现了环,那么说明不是一棵树,如果之后点数与边数加一不相等,也不是一棵树,所以需要记录点的个数,我用的是string类,每次find一下,最后求string的长度,有点儿偷懒屌丝了,不过发觉确实是方便,但是我的代码因此奇葩了不少……
一定要注意,空树也是一棵树,需要加条件判断,我就是因为少了一个条件,WA了好几次……
附代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 100000
int p[N], n, r;
string num;
int find(int x)
{
return p[x] != x ? p[x] = find(p[x]) : x;
}
void init()
{
for (int i = 1; i < N; i++)
p[i] = i;
n = 0; r = 0;
}
int main()
{
int t = 1;
int x, y;
int r1, r2;
bool j = 1;
init();
while (scanf("%d%d", &x, &y) != EOF)
{
if (x < 0 || y < 0) break;
if (x == 0 && y == 0)
{
int l = num.size();
if (l != r + 1 && l > 0) j = 0;
if (j) printf("Case %d is a tree.\n", t++);
else printf("Case %d is not a tree.\n", t++);
init();
num.clear();
j = 1;
continue;
}
if (x == y) j = 0;
if (num.find(x - '0') == -1) num.push_back(x - '0');
if (num.find(y - '0') == -1) num.push_back(y - '0');
r1 = find(x); r2 = find(y);
if (r1 == r2) j = 0;
if (r1 != r2)
{
p[r2] = r1;
r++;
}
}
return 0;
}