一本通1521:【 例 2】矿场搭建

这篇文章描述了一个C++程序,通过定义结构体和使用邻接表实现图的表示,利用深度优先搜索算法计算有向图中特定节点的路径数量,同时处理了权重和路径计数的优化。
摘要由CSDN通过智能技术生成
#include <bits/stdc++.h>
using namespace std;
#define int long long
inline int read() {
    int x = 0, f = 1;
    char ch = getchar();

    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;

        ch = getchar();
    }

    while (ch >= '0' && ch <= '9') {
        x = (x << 1) +
            (x << 3) + (ch ^ 48);
        ch = getchar();
    }

    return x * f;
}
//#define mo
#define M 510
#define N 1010
struct node {
    int x, y, n;
} d[M * 2];
int n, m, i, j, k, T;
int h[N], dep[N], c[N], w[N], f[N], zi[N];
int u, v, ansx, ansy, a, b;

void cun(int x, int y) {
    n = max(n, x);
    d[++k].x = x;
    d[k].y = y;
    d[k].n = h[x];
    h[x] = k;
}

void dfs(int x) {
    for (int g = h[x]; g; g = d[g].n) {
        int y = d[g].y;

        if (!dep[y]) {
            dep[y] = dep[x] + 1;
            dfs(y);

            if (dep[f[y]] >= dep[x])
                ++zi[x];

            if (dep[f[y]] < dep[f[x]])
                f[x] = f[y];
        } else if (dep[y] < dep[f[x]])
            f[x] = y;
    }
}

void foofill(int x) {
    for (int g = h[x]; g; g = d[g].n) {
        int y = d[g].y;

        if (c[y] < j) {
            c[y] = j;

            if (w[y])
                ++b;
            else ++a, foofill(y);
        }
    }
}

void init() {
    n = m = i = j = k = u = v = ansx = ansy = a = b = 0;
    memset(h, 0, sizeof(h));
    memset(dep, 0, sizeof(dep));
    memset(c, 0, sizeof(c));
    memset(w, 0, sizeof(w));
    memset(f, 0, sizeof(f));
    memset(zi, 0, sizeof(zi));
}

signed main() {
    //  freopen("tiaoshi.in","r",stdin);
    //  freopen("tiaoshi.out","w",stdout);
    while (1) {
        init();
        m = read();

        if (!m)
            return 0;

        printf("Case %lld: ", ++T);

        // printf("\n");
        for (i = 1; i <= m; ++i) {
            u = read();
            v = read();
            cun(u, v);
            cun(v, u);
        }

        // printf("%lld ", n);
        for (i = 1; i <= n; ++i)
            f[i] = i;

        for (i = 1; i <= n; ++i)
            if (!dep[i])
                dep[i] = 1, dfs(i);

        // for(i=1; i<=n; ++i)
        // printf("%lld %lld %lld\n", i, f[i], zi[i]);
        for (i = 1; i <= n; ++i)
            if ((dep[i] != 1 && zi[i]) || (zi[i] >= 2))
                w[i] = 1;

        // for(i=1; i<=n; ++i) printf("%lld ", w[i]);
        // printf("-------------------\n");
        ansy = 1;

        for (i = 1, j = 0; i <= n; ++i)
            if (c[i] == 0 && w[i] == 0 && h[i]) {
                c[i] = (++j);
                b = 0;
                a = 1;
                foofill(i);

                if (b == 0) {
                    if (a == 1)
                        ++ansx;
                    else
                        ansx += 2, ansy *= (a * (a - 1) / 2);
                } else if (b == 1)
                    ++ansx, ansy *= a;

                // printf("%lld %lld %lld %lld\n", i, a, b, j);
            }

        printf("%lld %lld\n", ansx, ansy);
    }

    return 0;
}

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值