• APIO2008 洛谷P3623 免费道路


    题目传送门:https://www.luogu.org/recordnew/show/6743108

    题解:写3次并查集,首先不妨留下所有水泥路,添加石子路,那么添加的石子路一定在答案内,留下所有石子路也一样,最后再添加其他边是等价的,注意k值即可,注意要判断好几次无解的情况。

    代码如下:

     1 #include<cstdio>
     2 #include<iostream>
     3 #define MN 20005
     4 #define MM 100005
     5 using namespace std;
     6 int n,m,k,fa[MN],u[MM],v[MM],c[MM],ans[MM],cnt;
     7 bool used[MM];
     8 int ff(int x){return fa[x]==x?x:fa[x]=ff(fa[x]);}
     9 bool check(){
    10     int tmp=ff(1);
    11     for(int i=2;i<=n;i++)
    12         if(ff(i)!=tmp) return false;
    13     return true;
    14 }
    15 bool work1(){
    16     for(int i=1;i<=n;i++) fa[i]=i;
    17     for(int i=1;i<=m;i++)
    18         if(c[i]){
    19             int x=ff(u[i]),y=ff(v[i]);
    20             if(x!=y) fa[y]=x;
    21         }
    22     for(int i=1;i<=m;i++)
    23         if(!c[i]){
    24             int x=ff(u[i]),y=ff(v[i]);
    25             if(x!=y) fa[y]=x,ans[++cnt]=i,used[i]=true;
    26         }
    27     if(k<cnt) return false;
    28     else k-=cnt;
    29     if(!check()) return false;
    30     return true;
    31 }
    32 bool work2(){
    33     for(int i=1;i<=n;i++) fa[i]=i;
    34     for(int i=1;i<=m;i++)
    35         if(!c[i]){
    36             int x=ff(u[i]),y=ff(v[i]);
    37             if(x!=y) fa[y]=x;
    38         }
    39     for(int i=1;i<=m;i++)
    40         if(c[i]){
    41             int x=ff(u[i]),y=ff(v[i]);
    42             if(x!=y) fa[y]=x,ans[++cnt]=i,used[i]=true;
    43         }
    44     if(!check()) return false;
    45     return true;
    46 }
    47 bool work3(){
    48     for(int i=1;i<=n;i++) fa[i]=i;
    49     for(int i=1;i<=cnt;i++){
    50         int x=ff(u[ans[i]]),y=ff(v[ans[i]]);
    51         if(x!=y) fa[y]=x;
    52         else return false;
    53     }
    54     for(int i=1;i<=m;i++){
    55         if(!k) break;
    56         if(!used[i]&&!c[i]){
    57             int x=ff(u[i]),y=ff(v[i]);
    58             if(x!=y) fa[y]=x,k--,ans[++cnt]=i;
    59         }
    60     }
    61     if(k) return false;
    62     for(int i=1;i<=m;i++)
    63         if(!used[i]&&c[i]){
    64             int x=ff(u[i]),y=ff(v[i]);
    65             if(x!=y) fa[y]=x,ans[++cnt]=i;
    66         }
    67     if(!check()) return false;
    68     return true;
    69 }
    70 int main()
    71 {
    72     scanf("%d%d%d",&n,&m,&k);
    73     for(int i=1;i<=m;i++) scanf("%d%d%d",&u[i],&v[i],&c[i]);
    74     if(!work1()){puts("no solution");return 0;}
    75     if(!work2()){puts("no solution");return 0;}
    76     if(!work3()){puts("no solution");return 0;}
    77     for(int i=1;i<=cnt;i++)
    78         printf("%d %d %d
    ",u[ans[i]],v[ans[i]],c[ans[i]]);
    79     return 0;
    80 }
  • 相关阅读:
    信息系统项目管理师沟通的四个好习惯
    Android 线程
    替换exe程序图标DLL
    Python 邮件类
    android自适应屏幕方向和大小
    sqlserver 存储过程
    FinalData 数据恢复工具[绿色版]
    Python Python 正则 取中括号值
    在Button任意位置加图片效果
    android GPRS
  • 原文地址:https://www.cnblogs.com/Beginner-/p/8798900.html
Copyright © 2020-2023  润新知