题目大意:给出你N条有向边,问能否形成一棵树
解题思路:并查集查看每个点是否在都连通,然后dfs判断是否有环
有特例, 0 0的时候是一棵树
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
const int INF = 0x3f3f3f3f;
int f[N], head[N];
int u, v, cas = 1, Min, Max, tot;
bool vis[N];
struct Edge{
int v, next;
Edge() {}
Edge(int v, int next): v(v), next(next) {}
}E[N];
int find(int x) {
return x == f[x] ? x : f[x] = find(f[x]);
}
void AddEdge(int u, int v) {
E[tot] = Edge(v, head[u]);
head[u] = tot++;
}
bool dfs(int u) {
vis[u] = true;
for (int i = head[u]; ~i; i = E[i].next) {
int v = E[i].v;
if (vis[v]) return false;
if (!dfs(v)) return false;
}
return true;
}
void solve() {
memset(head, -1, sizeof(head));
tot = 0;
for (int i = 0; i < N; i++)
f[i] = i;
AddEdge(u, v);
vis[u] = vis[v] = true;
Max = -INF, Min = INF;
Max = max(max(Max, u), v);
Min = min(min(Min, u), v);
if (u == 0 || v == 0) {
printf("Case %d is a tree.\n", cas++);
return ;
}
f[find(v)] = find(u);
while (scanf("%d%d" ,&u, &v) && u + v) {
AddEdge(u, v);
vis[u] = vis[v] = true;
int tx = find(u);
int ty = find(v);
if (tx != ty)
f[ty] = tx;
if (u < Min || v < Min)
Min = min(u, v);
if (u > Max || v > Max)
Max = max(u, v);
}
bool flag = false;
int root = find(Min);
for (int i = Min; i <= Max; i++) {
if (find(i) != root && vis[i]) {
flag = true;
break;
}
}
if (!flag) {
memset(vis, 0, sizeof(vis));
if (!dfs(root))
printf("Case %d is not a tree.\n", cas++);
else
printf("Case %d is a tree.\n", cas++);
}
else {
printf("Case %d is not a tree.\n", cas++);
}
}
int main() {
while (scanf("%d%d", &u, &v) != EOF) {
if (u == -1 && v == -1) break;
solve();
}
return 0;
}