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 }