zoukankan      html  css  js  c++  java
  • [luogu]P3623 [APIO2008]免费道路

    原题链接:P3623 [APIO2008]免费道路

    题意

    给定一个图(不一定连通),上面有$m$条$0$边和$1$边。

    要求选边使图连通,$0$边的数量必须等于$k$。

    分析

    一开始用很天真的想法加边:先加鹅卵石路,一直加到$k$条。然后再加水泥路,加到满。

    然后发现在洛谷上WA了一个点。

    仔细分析一下问题:一对点,如果我们加的是鹅卵石路,那么我们本可以用水泥路使这一对点连通,我们现在却使用了一次鹅卵石名额,这样子可能会导致后面鹅卵石名额不足。

    那么怎么考虑这个问题呢?

    我们发现只有用鹅卵石代替了水泥才会导致名额的冲突,那么我们只要求出有多少名额是必须给的(不给就不能连通的),然后优先给它们名额。

    至于剩下的,就先把鹅卵石的名额加到$k$,然后再加水泥路加到满就可以了。

    代码

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N=2e5+1000,M=3e5+1000;
     4 struct edge{
     5     int x,y;
     6 }sn[M],er[M];
     7 int read(){
     8     char c;int num,f=1;
     9     while(c=getchar(),!isdigit(c))if(c=='-')f=-1;num=c-'0';
    10     while(c=getchar(), isdigit(c))num=num*10+c-'0';
    11     return f*num;
    12 }
    13 int n,m,k,pre[N];
    14 int tot1=0,tot2=0,ans=0;
    15 int pt[M][4],vis[M];
    16 int fid(int x){return (x==pre[x])?x:(pre[x]=fid(pre[x]));}
    17 int main()
    18 {
    19     n=read();m=read();
    20     k=read();
    21     for(int i=1;i<=m;i++){
    22         int u,v,w;
    23         u=read();v=read();
    24         w=read();
    25         if(w==1){
    26             sn[++tot1].x=u;
    27             sn[  tot1].y=v;
    28         }else{
    29             er[++tot2].x=u;
    30             er[  tot2].y=v;
    31         }
    32     }
    33     if(tot2<k)goto no;
    34     int tt=0;
    35     for(int i=1;i<=n;i++)pre[i]=i;
    36     for(int i=1;i<=tot1;i++){
    37         if(fid(sn[i].x)!=fid(sn[i].y)){
    38             pre[fid(sn[i].x)]=fid(sn[i].y);
    39             tt++;
    40         }
    41     }
    42     int num=0;
    43     for(int i=1;i<=tot2;i++){
    44         if(fid(er[i].x)!=fid(er[i].y)){
    45             pre[fid(er[i].x)]=fid(er[i].y);
    46             vis[i]=1;
    47             num++;tt++;
    48         }
    49     }
    50     if(tt<n-1||num>k)goto no;
    51 
    52     for(int i=1;i<=n;i++)pre[i]=i;
    53     for(int i=1;i<=tot2;i++){
    54         if(vis[i]){
    55             pre[fid(er[i].x)]=fid(er[i].y);
    56             pt[++ans][1]=er[i].x;
    57             pt[  ans][2]=er[i].y;
    58             pt[  ans][3]=0;
    59             if(ans==k)break;
    60         }
    61     }
    62     for(int i=1;i<=tot2;i++){
    63         if(vis[i])continue;
    64         if(fid(er[i].x)!=fid(er[i].y)){
    65             pre[fid(er[i].x)]=fid(er[i].y);
    66             pt[++ans][1]=er[i].x;
    67             pt[  ans][2]=er[i].y;
    68             pt[  ans][3]=0;
    69             if(ans==k)break;
    70         }
    71     }
    72     if(ans<k)goto no;
    73     for(int i=1;i<=tot1;i++){
    74         if(fid(sn[i].x)!=fid(sn[i].y)){
    75             pre[fid(sn[i].x)]=fid(sn[i].y);
    76             pt[++ans][1]=sn[i].x;
    77             pt[  ans][2]=sn[i].y;
    78             pt[  ans][3]=1;
    79             if(ans==n-1)break;
    80         }
    81     }
    82     if(ans<n-1)goto no;
    83     for(int i=1;i<=ans;i++)
    84         printf("%d %d %d
    ",pt[i][1],pt[i][2],pt[i][3]);
    85     return 0;
    86 no:
    87     printf("no solution
    ");
    88     return 0;
    89 }
    View Code
  • 相关阅读:
    zTree根据json选中节点,并且设置其他节点不可选
    点击一次按钮,发生多次ajax请求
    sublimeText3 中配置sass环境,并将编译后文件保存到指定文件夹
    MD5加密
    c# Http请求之HttpClient
    xml与object 之间的ORM
    wpf和winform的那点区别
    c# http请求ajax页面
    c# https请求
    python爬虫框架Pyspider初次接触
  • 原文地址:https://www.cnblogs.com/onglublog/p/10024242.html
Copyright © 2011-2022 走看看