HDU 1325 Is It A Tree?
这个题是判断是否为树。
树的边是有向的,树也可以为空。
代码里面,s
指子结点集,total
指结点集,v
指边集。
还有一个坑,最后结束标志是负数而不一定-1
?
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <unordered_set>
using namespace std;
const int MAXN = 1e6;
int a, b;
int c = 1;
int conn = 0;
int pre[MAXN];
struct Edge
{
int from, to;
};
vector<Edge> v;
unordered_set<int> s;
unordered_set<int> total;
int f(int n)
{
int f0 = n, f1 = n;
int t;
for (; pre[f0] > 0;)
{
f0 = pre[f0];
}
for (; pre[f1] > 0;)
{
t = f1;
f1 = pre[f1];
pre[t] = f0;
}
return f0;
}
bool u(int n1, int n2)
{
int f1 = f(n1);
int f2 = f(n2);
if (f1 != f2)
{
conn++;
if (pre[f1] <= pre[f2])
{
pre[f1] += pre[f2];
pre[f2] = f1;
}
else
{
pre[f2] += pre[f1];
pre[f1] = f2;
}
return true;
}
return false;
}
void judge()
{
if (v.size() == 0)
{
printf("Case %d is a tree.\n", c);
return;
}
if (v.size() != s.size())
{
printf("Case %d is not a tree.\n", c); // 判定重指
return;
}
for (int i = 0; i < v.size(); i++)
{
if (!u(v[i].from, v[i].to))
{
printf("Case %d is not a tree.\n", c); // 判定一切环,包括有环连通图和有环非连通图
return;
}
}
if (conn + 1 != total.size()) // 此时conn已经等于v.size()
{
printf("Case %d is not a tree.\n", c); // 判定无环非连通图
return;
}
printf("Case %d is a tree.\n", c);
}
// 顺便说一句,v.size()+1!=total.size()应付不了有环非连通图
int main()
{
memset(pre, -1, sizeof pre);
for (; ~scanf("%d%d", &a, &b);)
{
if (a < 0) break; // 坑!
if (a == 0)
{
judge();
memset(pre, -1, sizeof pre);
c++;
conn = 0;
v.clear();
s.clear();
total.clear();
continue;
}
v.push_back({ a,b });
s.insert(b);
total.insert(a);
total.insert(b);
}
return 0;
}