最小树形图求调
  • 板块学术版
  • 楼主XFlypig
  • 当前回复1
  • 已保存回复1
  • 发布时间2023/8/28 22:39
  • 上次更新2023/11/3 00:36:43
查看原帖
最小树形图求调
1012734
XFlypig楼主2023/8/28 22:39

不知道哪里错了

题目

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 110;
const LL INF = 1e10;

int n, m, root;
LL d[N][N], bd[N][N];
int pre[N], bpre[N];
int dfn[N], low[N], ts, stk[N], top;
int id[N], cnt;
bool st[N], ins[N];

void dfs(int u)
{
    st[u] = true;
    for (int i = 1; i <= n; i ++ )
        if (d[u][i] < INF && !st[i])
            dfs(i);
}

bool check_con()
{
    dfs(root);
    for (int i = 1; i <= n; i ++ )
        if (!st[i])
            return false;
    return true;
}

void tarjan(int u)
{
    dfn[u] = low[u] = ++ ts;
    stk[ ++ top] = u, ins[u] = true;

    int j = pre[u];
    if (!dfn[j])
    {
        tarjan(j);
        low[u] = min(low[u], low[j]);
    } else if (ins[j]) low[u] = min(low[u], dfn[j]);

    if (low[u] == dfn[u])
    {
        int y;
        ++ cnt;
        do
        {
            y = stk[top -- ], ins[y] = false, id[y] = cnt;
        } while (y != u);
    }
}

LL work()
{
    LL res = 0;
    while (true)
    {
        for (int i = 1; i <= n; i ++ )
        {
            pre[i] = i;
            for (int j = 1; j <= n; j ++ )
                if (d[pre[i]][i] > d[j][i])
                    pre[i] = j;
        }

        memset(dfn, 0, sizeof dfn);
        ts = cnt = 0;
        for (int i = 1; i <= n; i ++ )
            if (!dfn[i])
                tarjan(i);

        if (cnt == n)
        {
            for (int i = 1; i <= n; i ++ )
                if(i != root)
                    res += d[pre[i]][i];
            break;
        }

        for (int i = 1; i <= n; i ++ )
            if (i != root && id[pre[i]] == id[i])
                res += d[pre[i]][i];

        for (int i = 1; i <= cnt; i ++ )
            for (int j = 1; j <= cnt; j ++ )
                bd[i][j] = INF;

        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= n; j ++ )
                if (d[i][j] < INF && id[i] != id[j])
                {
                    int a = id[i], b = id[j];
                    if (id[pre[j]] == id[j]) bd[a][b] = min(bd[a][b], d[i][j] - d[pre[j]][j]);
                    else bd[a][b] = min(bd[a][b], d[i][j]);
                }

        n = cnt;
        memcpy(d, bd, sizeof d);
    }

    return res;
}

int main()
{
    scanf("%d%d%d", &n, &m, &root);

    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= n; j ++ )
            d[i][j] = INF;

    while (m -- )
    {
        int a, b;
        LL c;
        scanf("%d%d%lld", &a, &b, &c);
        if (a != b && b != root) d[a][b] = min(d[a][b], c);
    }

    if (!check_con()) puts("-1");
    else printf("%lld\n", work());

    return 0;
}
2023/8/28 22:39
加载中...