ZOJ 2966 Build The Electric System MST

题意抽象一下:

初始:一个图中有几个连通分支 。你可以连通任意两个点。求在满足使这个图成为连通图的前提下,使你所连的两点间的边的sum(权值)最小。

 

解题思路:

这个很容易让人想到Kruskal算法中,构造到一半的MST。把以有的连通分支各缩为一个点,接下来我们只用继续完成这颗树就好啦。

 

 

#include <cstdio> #include <algorithm> #define MAXN 125000 using namespace std; int u[MAXN], v[MAXN], w[MAXN], r[MAXN], par[MAXN]; int E, N; void bin(int uf, int vf) { par[uf] = vf; } int find(int x) { return x == par[x] ? x : par[x] = find(par[x]); } bool cmp(const int &a, const int &b) { return w[a] < w[b]; } int main () { int T, a, b, ut, vt, wt, ecnt, flag, sum, t; scanf("%d", &T); while(T--) { scanf("%d%d", &N, &E); for(int i = 0; i < N; i++) { par[i] = i; } ecnt = 0; for(int i = 0; i < E; i++) { scanf("%d%d%d", &ut, &vt, &wt); if(wt == 0) { a = find(ut); b = find(vt); if(a != b) { bin(a, b); } } else { u[ecnt] = ut; v[ecnt] = vt; w[ecnt] = wt; r[ecnt] = ecnt; ecnt++; } } sum = 0; flag = 1; for(int j = 1; j < N; j++) { if(find(j) != find(j-1)) { flag = 0; break; } } if(flag) { printf("%d/n", sum); continue; } sort(r, r+ecnt, cmp); for(int i = 0; i < ecnt; i++) { t= r[i]; ut = u[t]; vt = v[t]; a = find(ut); b = find(vt); if(a != b) { bin(a, b); sum += w[t]; flag = 1; for(int j = 1; j < N; j++) { if(find(j) != find(j-1)) { flag = 0; break; } } if(flag) { printf("%d/n", sum); break; } } } } return 0; } 

你可能感兴趣的:(ZOJ 2966 Build The Electric System MST)