Is It A Tree? HDU - 1325 (有向图判断是否是树)

发布时间 2023-03-23 15:00:45作者: HelloHeBin

题意:有向图判断是否是树。

树是一种众所周知的数据结构,它要么是空的,要么是一组由足以下条件的节点之间的定向边连接的一个或多个节点。

正好有一个节点,称为根,没有定向边指向该节点。
除了根节点外,每个节点都有一条指向它的边。
从根到每个节点都有一个唯一的有向边序列。

分析:对于一棵非空树,有如下性质

  1. 每个点入度为0或1.
  2. 入读为0的点只有一个,且由该点可以单向遍历到其余全部点.
  3. 点数 n = 边数 m + 1.
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10, INF = 0x3f3f3f3f;

int n, m, h[N], idx;
struct T {
    int to, nx;
} g[N];
int in[N], out[N], st[N];

void add(int u, int v) {
    g[idx] = {v, h[u]}, h[u] = idx++;
}
int dfs(int u) {  // 记录该树的所有节点数量
    int res = 1; st[u] = 1;
    for (int i = h[u]; ~i; i = g[i].nx) {
        int v = g[i].to;
        if (!st[v]) res += dfs(v);
    }
    return res;
}
bool flag = 1;
bool is_tree() {
    if (n == 0) return 1;  // 空树
    if (!flag) return 0;  // 入度 > 1
    int rt = 0;
    for (int i = 1; i <= n; i++) {
        if (!in[i] && out[i]) {
            rt = i; break; // 根节点 rt, 记录该树的节点数量
        }
    }
    if (rt == 0) return 0;
    int k = dfs(rt);
    // printf("k,m: %d %d\n", k, m);
    return k == m + 1;
}
int main_ac() {
    int a, b, t = 0;
    memset(h, -1, sizeof(h)), idx = 0, n = 0, m = 0;
    while (~scanf("%d%d", &a, &b), ~a) {
        if (a + b == 0) {
            printf("Case %d is%s a tree.\n", ++t, is_tree() ? "" : " not");

            memset(h, -1, sizeof(h)), idx = 0, n = 0, m = 0, flag = 1;
            memset(in, 0, sizeof(in));
            memset(out, 0, sizeof(out));
            memset(st, 0, sizeof(st));
            continue;
        }
        add(a, b), m++, n = max(n, max(a, b)), in[b]++, out[a]++;
        if (in[b] > 1)
            flag = 0;
    }
    return 0;
}
/********************/
bool is_tree2() {
    // printf("chk: %d %d %d\n", n, m, flag);
    return n == 0 || n == m + 1 && flag;
}
int main() {
    int a, b, t = 0;
    while (~scanf("%d%d", &a, &b) && ~a) {
        if (a + b == 0) {
            printf("Case %d is%s a tree.\n", ++t, is_tree2() ? "" : " not");
            n = 0, m = 0, flag = 1;
            memset(in, 0, sizeof(in));
            memset(out, 0, sizeof(out));
            continue;
        }
        m++;
        n += !(out[a] + in[a]), out[a]++;
        n += !(out[b] + in[b]), in[b]++;
        if (in[b] > 1) flag = 0;
    }
    return 0;
}