这道题我用的是并查集(union-find)确定没有环,再看看边数是不是节点数减一(确定是否联通)做的。
AC后看了discuss,发现并不能通过2 1 3 1 0 0 这种数据(但是OJ上没有这样的数据)。看来还是需要检查每个节点的入度,保证一个节点入度为0,其余节点入度为1。
注意空树也是树。
thestoryofsnow | 1308 | Accepted | 7992K | 0MS | C++ |
/*
ID: thestor1
LANG: C++
TASK: poj1308
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <cassert>
using namespace std;
const int MAXN = 1000000;
void makeset(const int N, std::vector<int> &parent, std::vector<int> &rank)
{
for (int u = 0; u < N; ++u)
{
parent[u] = u;
rank[u] = 0;
}
}
int find(int u, std::vector<int> &parent)
{
if (parent[u] != u)
{
parent[u] = find(parent[u], parent);
}
return parent[u];
}
void union_set(int u, int v, std::vector<int> &parent, std::vector<int> &rank)
{
int ru = find(u, parent);
int rv = find(v, parent);
if (ru == rv)
{
return;
}
if (rank[ru] < rank[rv])
{
parent[ru] = rv;
}
else if (rank[rv] < rank[ru])
{
parent[rv] = ru;
}
else
{
parent[ru] = rv;
rank[rv]++;
}
}
int main()
{
std::vector<int> parent(MAXN), rank(MAXN);
int u, v;
int caseno = 1;
while (true)
{
bool istree = true;
int vno = 0, eno = 0;
map<int, int> utovno;
while (scanf("%d%d", &u, &v) && u > 0 && v > 0)
{
eno++;
assert(vno < MAXN);
if (utovno.find(u) == utovno.end())
{
utovno[u] = vno;
u = vno;
parent[u] = u;
rank[u] = 0;
vno++;
}
else
{
u = utovno[u];
}
if (utovno.find(v) == utovno.end())
{
utovno[v] = vno;
v = vno;
parent[v] = v;
rank[v] = 0;
vno++;
}
else
{
v = utovno[v];
}
if (find(u, parent) == find(v, parent))
{
istree = false;
}
union_set(u, v, parent, rank);
}
if (u < 0 || v < 0)
{
break;
}
assert(vno < MAXN);
if (istree)
{
istree = (eno == 0 || eno == vno - 1);
}
if (istree)
{
printf("Case %d is a tree.\n", caseno);
}
else
{
printf("Case %d is not a tree.\n", caseno);
}
caseno++;
}
return 0;
}