51nod——1640 天气晴朗的魔法 有边权限制的最大生成树

  好好读题嗷:“所以我们要求阵中的魔法链的魔力值最大值尽可能的小,与此同时,魔力值之和要尽可能的大。”

  第一条件是生成树的最大边权更小,第二条件是在最大边权的限制下搞一个最大生成树。

  至于最大生成树,如果用prime就把边权全都置负,如果用kruskal就把边权降序排列,生成的时候加一个小判断。

  

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define maxn 200050
 4 struct edge { int u, v, cost; } es[maxn];//连接顶点u和v的边,权值为cost
 5 bool cmp1(edge e1, edge e2){
 6     return e1.cost < e2.cost;
 7 }
 8 bool cmp2(edge e1, edge e2){
 9     return e1.cost > e2.cost;
10 }
11 int V,E;//顶点数和边数
12 
13 //并查集部分
14 int par[maxn];
15 int find(int a){
16     return a==par[a]?a:(par[a]=find(par[a]));
17 }
18 void unite(int a,int b){
19     par[find(b)]=find(a);
20 }
21 
22 int kruskal1(){//返回最小生成树的最大边权
23     sort(es,es+E,cmp1);
24     int res=0;
25     for(int i=0;i<E;i++){
26         edge e = es[i];
27         if(find(e.u)!=find(e.v)){
28             unite(e.u,e.v);
29             res=max(res,e.cost);
30         }
31     }
32     return res;
33 }
34 long long kruskal2(int k){//返回边权均小于k的最大生成树的边权和
35     sort(es,es+E,cmp2);
36     long long res=0;
37     for(int i=0;i<E;i++){
38         edge e = es[i];
39         if(find(e.u)!=find(e.v)&&e.cost<=k){
40             unite(e.u,e.v);
41             res+=e.cost;
42         }
43     }
44     return res;
45 }
46 int main(){
47     std::ios::sync_with_stdio(0);
48     cin.tie(0);
49     cin>>V>>E;
50     for(int i=0;i<=V;i++) par[i]=i;
51     for(int i=0;i<E;i++)
52         cin>>es[i].u>>es[i].v>>es[i].cost;
53     int k=kruskal1();
54 
55     for(int i=0;i<=V;i++) par[i]=i;
56     long long ans=kruskal2(k);
57     cout<<ans<<endl;
58     return 0;
59 }
原文地址:https://www.cnblogs.com/noobimp/p/10946823.html