• 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 }
  • 相关阅读:
    session和cookie
    数据库备份
    使用pip安装.whl文件时出现is not a supported wheel on this platform的解决办法
    multiprocessing模块
    threading模块
    python中多线程相关
    python中实现单例模式
    Flask-SQLAlchemy相关与Flask-Migrate相关
    redis模块
    Flask-Login中装饰器@login_manager.user_loader的作用及原理
  • 原文地址:https://www.cnblogs.com/Menhera/p/9507804.html
Copyright © 2020-2023  润新知