加油 ( •̀ ω •́ )y!

51nod 天气晴朗的魔法 - (Kruskall最小生成树)

题目:   基准时间限制:1 秒 空间限制:131072 KB 
51nod魔法学校近日开展了主题为“天气晴朗”的魔法交流活动。
 
N名魔法师按阵法站好,之后选取N - 1条魔法链将所有魔法师的魔力连接起来,形成一个魔法阵。
 
魔法链是做法成功与否的关键。每一条魔法链都有一个魔力值V,魔法最终的效果取决于阵中所有魔法链的魔力值的和。
 
由于逆天改命的魔法过于暴力,所以我们要求阵中的魔法链的魔力值最大值尽可能的小,与此同时,魔力值之和要尽可能的大。
 
现在给定魔法师人数N,魔法链数目M。求此魔法阵的最大效果。
Input
两个正整数N,M。(1 <= N <= 10^5, N <= M <= 2 * 10^5)

接下来M行,每一行有三个整数A, B, V。(1 <= A, B <= N, INT_MIN <= V <= INT_MAX)

保证输入数据合法。
Output
输出一个正整数R,表示符合条件的魔法阵的魔力值之和。
Input示例
4 6
1 2 3
1 3 1
1 4 7
2 3 4
2 4 5
3 4 6
Output示例
12

关于思路: 这道题可以先用最小生成树求出最大权值边,然后再用权值小于等于最大权值的边做一次最大生成树的做法求解

代码如下:
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector> 
 5 typedef long long LL;
 6 using namespace std;
 7 const int maxn=200005;
 8 struct node{
 9     LL u,v,w;
10     node(){}
11     node(LL a,LL b,LL c):u(a),v(b),w(c){}
12 };
13 LL f[maxn];
14 LL n,m;
15 vector<node>edge;
16 int Find(LL x)
17 {
18     if (f[x] != x)
19         f[x] = Find(f[x]);
20     return f[x];
21 }
22 
23 void Union(LL a, LL b)
24 {
25     int a1 = Find(a);
26     int b1 = Find(b);
27     if (a1 != b1)
28         f[a1] = b1;
29 }
30 bool cmp1(node a,node b)
31 {
32     return a.w>b.w;
33 }
34 bool cmp2(node a,node b)
35 {
36     return a.w<b.w;
37 }
38 int main()
39 {
40     ios::sync_with_stdio(false);
41     cin>>n>>m;
42     for(int i=1;i<=n;i++)
43         f[i]=i;
44     for(int i=0;i<m;i++){
45         LL a,b,c;
46         cin>>a>>b>>c;
47         edge.push_back(node(a,b,c));
48     }
49     sort(edge.begin(),edge.end(),cmp2);
50     LL k=0,max_num=-1;
51     for(int i=0;i<m;i++)
52     {
53         if(Find(edge[i].u)!=Find(edge[i].v))
54         {
55             Union(edge[i].u,edge[i].v);
56             max_num = max(max_num,edge[i].w);
57             k++;
58         }
59         if(k==(n-1))
60             break;
61     }
62     sort(edge.begin(),edge.end(),cmp1);
63     for(int i=1;i<=m;i++)
64         f[i]=i;
65     LL ans=0;
66     k=0;
67     for(int i=0;i<m;i++)
68     {
69         if(edge[i].w>max_num)continue;
70         if(Find(edge[i].u)!=Find(edge[i].v))
71         {
72             Union(edge[i].u,edge[i].v);
73             ans += edge[i].w;
74             k++;
75         }
76         if(k==(n-1))
77             break;
78     }
79     cout<<ans<<endl;
80     return 0;
81 }

 

 



posted @ 2017-10-31 20:32  皮皮虎  阅读(298)  评论(0编辑  收藏  举报