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 }
Stay Hungry, Stay Foolish