两个正整数N,M。(1 <= N <= 10^5, N <= M <= 2 * 10^5) 接下来M行,每一行有三个整数A, B, V。(1 <= A, B <= N, INT_MIN <= V <= INT_MAX) 保证输入数据合法。
输出一个正整数R,表示符合条件的魔法阵的魔力值之和。
4 6 1 2 3 1 3 1 1 4 7 2 3 4 2 4 5 3 4 6
12
关于思路: 这道题可以先用最小生成树求出最大权值边,然后再用权值小于等于最大权值的边做一次最大生成树的做法求解
代码如下:
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 5 typedef long long LL; 6 using namespace std; 7 const int maxn=200005; 8 struct node{ 9 LL u,v,w; 10 }edge[maxn]; 11 LL f[maxn]; 12 LL n,m; 13 14 int Find(LL x) 15 { 16 if (f[x] != x) 17 f[x] = Find(f[x]); 18 return f[x]; 19 } 20 21 void Union(LL a, LL b) 22 { 23 int a1 = Find(a); 24 int b1 = Find(b); 25 if (a1 != b1) 26 f[a1] = b1; 27 } 28 bool cmp1(node a,node b) 29 { 30 return a.w>b.w; 31 } 32 bool cmp2(node a,node b) 33 { 34 return a.w<b.w; 35 } 36 int main() 37 { 38 ios::sync_with_stdio(false); 39 cin>>n>>m; 40 for(int i=1;i<=n;i++) 41 f[i]=i; 42 for(int i=0;i<m;i++) 43 cin>>edge[i].u>>edge[i].v>>edge[i].w; 44 sort(edge,edge+m,cmp2); 45 LL k=0,max_num=-1; 46 for(int i=0;i<m;i++) 47 { 48 if(Find(edge[i].u)!=Find(edge[i].v)) 49 { 50 Union(edge[i].u,edge[i].v); 51 max_num = max(max_num,edge[i].w); 52 k++; 53 } 54 if(k==(n-1)) 55 break; 56 } 57 sort(edge,edge+m,cmp1); 58 for(int i=1;i<=m;i++) 59 f[i]=i; 60 LL ans=0; 61 k=0; 62 for(int i=0;i<m;i++) 63 { 64 if(edge[i].w>max_num)continue; 65 if(Find(edge[i].u)!=Find(edge[i].v)) 66 { 67 Union(edge[i].u,edge[i].v); 68 ans += edge[i].w; 69 k++; 70 } 71 if(k==(n-1)) 72 break; 73 } 74 cout<<ans<<endl; 75 return 0; 76 }
51nod 天气晴朗的魔法 - (Kruskall最小生成树)
原文:http://www.cnblogs.com/wangrunhu/p/7763509.html