zoukankan      html  css  js  c++  java
  • 3624: [Apio2008]免费道路

     

    Description

     

    Input

     

    Output

     

    Sample Input

    5 7 2

    1 3 0

    4 5 1

    3 2 0

    5 3 1

    4 3 0

    1 2 1

    4 2 1

    Sample Output

    3 2 0

    4 3 0

    5 3 1

    1 2 1

    /*  比较优秀的一道题

        我们对于这个K上来第一反应可能就是先找k个0,别的再说

    但这个显然错误。(没准只有我个蒟蒻真试了=-=)

        但是我们反过来想,如果c值为1的边和小于k条的c值为0的

    边,能够使得这个图成立(即树)。那么我们将其中的一些c值

    为1的边替换成c值为0的边,这个图还能成立。

        证明我们可以这么想,首先我们已经搞出了一棵树,当我们

    砍掉一条树枝时,就分成了两个树(这里一个点也看作一棵树),

    即树a,树b,我们刚才砍了一条边,就要补一条边,补上的这

    条边显然不可以是a中一点连a中另一点,b同理(万恶的并查集)

    ,那么只能是a中的某一点连到b中的某一点,那么此时它又变成

    了一棵树。

        同时还有一件事就是,对于c值为1的边,无论链接顺序怎样

    最后连接的边数都是定值。(这里指用c值为1的边贪心的生成树)。

        然后一切就都好办了,先贪心跑一遍c值为1的边,再在此基

    础上跑c值为0的边(即最少需要c值为0的边的边数)。若此时不

    能构成一颗完全的树,或者最少需要的c值为0的边的边数都大于

    K显然无解。反之,我们把刚才用到的c值为0的边全部使用,再

    补上剩下c值为0的边来满足K,如果不够k,无解。否则我们再跑

    c值为1的就好了。

    【注】 这个大视野卡回车啊!!!

     1 #include<cstdio>
     2 using namespace std;
     3 const int N=100100;
     4 struct edges{int u,v,c;}edge[N];
     5 int n,m,k;
     6 int stack[N],top;
     7 int beg[2],ed[2];
     8 int fa[N];
     9 bool chos[N];
    10 int find(int x){    return x==fa[x]?x:fa[x]=find(fa[x]);}
    11 int sum[2];
    12 void solve(int op,int up){
    13     for(int i=1;i<=m&&sum[op]<up;i++){
    14         if(edge[i].c==op){
    15             int u=edge[i].u,v=edge[i].v;
    16             u=find(u),v=find(v);
    17             if(u!=v){
    18                 sum[op]++;fa[v]=u;stack[++top]=i;chos[i]=true;
    19             }   
    20         }
    21     }
    22 }
    23 
    24 void special(){
    25     for(int i=1;i<=m;i++){
    26         if(edge[i].c==0&&chos[i]){
    27             int u=edge[i].u,v=edge[i].v;
    28             u=find(u),v=find(v);
    29             if(u!=v){
    30                 fa[v]=u;
    31                 stack[++top]=i;
    32                 sum[0]++;
    33             }
    34         }
    35     }
    36 }
    37 int main(){
    38     scanf("%d%d%d",&n,&m,&k);
    39     for(int i=1;i<=m;i++){    
    40         scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].c);
    41         }
    42     for(int i=1;i<=n;i++)   fa[i]=i;
    43     solve(1,N);
    44     solve(0,N);
    45     if(sum[0]+sum[1]<n-1||sum[0]>k){
    46         printf("no solution
    ");
    47         return 0;
    48     }
    49     top=0;
    50     for(int i=1;i<=n;i++){fa[i]=i;}
    51     sum[0]=sum[1]=0;
    52     special();
    53     solve(0,k);
    54     if(sum[0]<k)   {
    55         printf("no solution
    ");return 0;
    56     }
    57     solve(1,n-1-k);
    58     for(int i=1,j;i<=top;i++){
    59         j=stack[i];
    60             printf("%d %d %d
    ",edge[j].u,edge[j].v,edge[j].c);
    61     }
    62 }
  • 相关阅读:
    测试方案
    测试需求
    软件测试知识点总结
    自动化测试
    测试——缺陷报告包括那些内容,由什么组成
    测试——缺陷的类型
    软件测试工具简介
    测试工程师
    剑指offer系列21--二叉搜索树的后续遍历序列
    剑指offer系列20--从上到下打印二叉树
  • 原文地址:https://www.cnblogs.com/Troywar/p/7242167.html
Copyright © 2011-2022 走看看