Codeforces1023F Mobile Phone Network 【并查集】【最小生成树】

题目大意:

给一些没安排权值的边和安排了权值的边,没被安排的边全要被选入最小生成树,问你最大能把它们的权值和安排成多少。
题目分析:
假设建好了树,那么树边与剩下的每一条边都能构成一个环,并且非树边的权值是环中最大的,所以钦定边权不大于非树边即可。用并查集维护一下。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 501000;
 5 
 6 int n,k,m;
 7 struct edge{int from,to,w;}p1[maxn],p2[maxn];
 8 int pre[maxn],arr[maxn],minn[maxn],dep[maxn],fa[maxn],fd[maxn];
 9 vector<int> g[maxn];
10 
11 int found(int x){
12     int rx = x; while(pre[rx] != rx) rx = pre[rx];
13     while(pre[x] != rx){int tmp = pre[x]; pre[x] = rx; x = tmp;}
14     return rx;
15 }
16 
17 void read(){
18     scanf("%d%d%d",&n,&k,&m);
19     for(int i=1;i<=k;i++){scanf("%d%d",&p1[i].from,&p1[i].to);}
20     for(int i=1;i<=m;i++){scanf("%d%d%d",&p2[i].from,&p2[i].to,&p2[i].w);}
21 }
22 
23 void dfs(int now,int dp,int f){
24     dep[now] = dp; fa[now] = f;
25     for(int i=0;i<g[now].size();i++){
26     int to;int z = g[now][i];
27     if(z > 0){
28         if(p1[z].to == now) to = p1[z].from;
29         else to = p1[z].to;
30     }else{
31         if(p2[-z].to == now) to = p2[-z].from;
32         else to = p2[-z].to;
33     }
34     if(to == f) continue;
35     if(z) fd[to] = z;
36     dfs(to,dp+1,now);
37     }
38 }
39 
40 void work(){
41     for(int i=1;i<=n;i++) pre[i] = i;
42     for(int i=1;i<=k;i++){
43     if(found(p1[i].from) != found(p1[i].to)){
44         pre[found(p1[i].from)] = found(p1[i].to);
45         g[p1[i].from].push_back(i); g[p1[i].to].push_back(i);
46     }
47     }
48     for(int i=1;i<=m;i++){
49     if(found(p2[i].from) != found(p2[i].to)){
50         pre[found(p2[i].from)] = found(p2[i].to);
51         g[p2[i].from].push_back(-i); g[p2[i].to].push_back(-i);
52         arr[i] = 1;
53     }
54     }
55     dfs(1,1,0);
56     for(int i=1;i<=n;i++) minn[i] = 1000000006,pre[i]=i;
57     for(int i=1;i<=m;i++){
58     if(arr[i] == 0){
59         int u = found(p2[i].from),v = found(p2[i].to);
60         while(u != v){
61         if(dep[u] >= dep[v]){
62             int z = found(fa[u]);
63             if(z!=0)pre[u] = z; minn[fd[u]] = p2[i].w; u = z;
64         }else{
65             int z = found(fa[v]);
66             if(z!=0)pre[v] = z; minn[fd[v]] = p2[i].w; v = z;
67         }
68         }
69     }
70     }
71     long long ans = 0;
72     for(int i=1;i<=k;i++){
73     if(minn[i] == 1000000006) {puts("-1");return;}
74     else ans += minn[i];
75     }
76     printf("%I64d",ans);
77 }
78 
79 int main(){
80     read();
81     work();
82     return 0;
83 }

 

posted @ 2018-08-20 20:12  menhera  阅读(351)  评论(0编辑  收藏  举报