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

不知道这个写法哪里错了

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

using namespace std;

typedef long long LL;

const LL N = 110, INF = 1e18;

int n, m, root;
int pre[N];
LL d[N][N], bd[N][N];
int dfn[N], low[N], ts;
int 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(dfn[u] == low[u])
    {
        cnt ++ ;
        int y;
        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(id[pre[i]] == id[i] && i != root)
                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;
    
    for (int i = 1; i <= m; i ++ )
    {
        LL a, b, c;
        scanf("%lld%lld%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:00
加载中...