Pseudoforest 【HDU - 3367】【最大生成樹】【Kruskal】
阿新 • • 發佈:2018-11-20
題目連結
題意:好坑的題啊,我一開始看了測試樣例以為是放進一棵樹中問最大的邊,每棵樹上最多成一個環,沒想可以放進多棵樹中,但是要求的是最大的邊權總和就行,那麼就是Kruskal的思想了,以降序排序,然後逐步存入邊,遇到已經成環的就放棄掉這條邊,因為它一定不是最優解。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxN=10005; int N, M, root[maxN], num[maxN]; void init() { for(int i=0; i<N; i++) { root[i]=i; num[i]=0; } } struct Eddge { int no, to, val; Eddge(int a=0, int b=0, int c=0):no(a), to(b), val(c) {} }path[maxN*10]; bool cmp(Eddge e1, Eddge e2) { return e1.val>e2.val; } int fid(int x) { return x==root[x]?x:(root[x]=fid(root[x])); } ll kruskal() { ll ans=0; for(int i=1; i<=M; i++) { int u=fid(path[i].no), v=fid(path[i].to), cost=path[i].val; if(u!=v) { if(num[u] && num[v]) continue; root[u]=v; num[v]+=num[u]; ans+=cost; } else if(num[u]==0) { num[v]++; ans+=cost; } } return ans; } int main() { while(scanf("%d%d", &N, &M) && (N || M)) { init(); for(int i=1; i<=M; i++) { scanf("%d%d%d", &path[i].no, &path[i].to, &path[i].val); } sort(path+1, path+1+M, cmp); printf("%lld\n", kruskal()); } return 0; }