UVA 11183 - Teen Girl Squad(最小树形图)

题目链接 https://cn.vjudge.net/problem/UVA-11183

【题意】
给定n个节点m条边的有向带权图,求以0为根节点的最小树形图权值大小

【思路】
最小树形图模板题,直接套板子

#include<bits/stdc++.h>
using namespace std;

const int inf = 2e9;
const int maxn = 1005;
const int maxm = 40005;

int n, m;
int in[maxn];
int pre[maxn];
int used[maxn], id[maxn];

struct Edge {
    int from, to;
    int dist;
    Edge(int f = 0, int t = 0, int d = 0) :from(f), to(t), dist(d) {}
}edges[maxm];

int direct_mst(int root, int V, int E) {
    int ans = 0;
    while (1) {
        for (int i = 0; i < V; ++i) in[i] = inf;
        for (int i = 0; i < E; ++i) {
            int u = edges[i].from;
            int v = edges[i].to;
            if (in[v] > edges[i].dist && u != v) {
                in[v] = edges[i].dist;
                pre[v] = u;
            }
        }
        for (int i = 0; i < V; ++i) {
            if (i == root) continue;
            if (inf == in[i]) return -1;
        }

        int cnt = 0;
        memset(id, -1, sizeof(id));
        memset(used, -1, sizeof(used));
        in[root] = 0;
        for (int i = 0; i < V; ++i) {
            ans += in[i];
            int v = i;
            while (used[v] != i && id[v] == -1 && v != root) { 
                used[v] = i;
                v = pre[v];
            }
            if (v != root && id[v] == -1) {
                for (int u = pre[v]; u != v; u = pre[u]) id[u] = cnt;
                id[v] = cnt++;
            }
        }

        if (0 == cnt) break;

        for (int i = 0; i < V; i++)
            if (id[i] == -1) id[i] = cnt++;

        for (int i = 0; i < E; i++) {
            int u = edges[i].from;
            int v = edges[i].to;
            edges[i].from = id[u];
            edges[i].to = id[v];
            if (id[u] != id[v]) edges[i].dist -= in[v];
        }
        V = cnt;
        root = id[root];
    }
    return ans;
}

int main(){
    int T;
    scanf("%d",&T);
    for(int kase=1;kase<=T;++kase){
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;++i){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            edges[i]=Edge(u,v,w);
        }
        int ans=direct_mst(0,n,m);
        printf("Case #%d: ",kase);
        if(ans<0) puts("Possums!");
        else printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiao_k666/article/details/82662244
今日推荐