• bzoj3624(Apio2008):免费道路


    题目↓

    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
     
    芒果君:很明显最小生成树。我一开始的想法有点接近正解(80分),如果一个点连接的边都是0边,而规定的额度k已经用完,就无法再跑kruskal,为了避免这种情况发生,我把这样的点连接的边权值改为-1(使得它们能被优先选)。改题的时候我想到如果一个“0点”连接了很多0边,它就会产生问题——有些与0点连接的点可以被1边更新,却用了0的额度,导致其他的0点无法被更新。
    所以第一遍kruskal只用1边,找出0点(它是当前森林中树的祖宗,不一定只连接了0边,这也补了上面算法漏洞),再根据优先级跑第二遍。无解的判断需要特别注意。
     
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<iostream>
     6 #include<ctime>
     7 #include<map>
     8 #define maxn 20010
     9 #define maxm 100010
    10 using namespace std;
    11 struct Edge{
    12     int u,v,w,f;
    13 }e[maxm];
    14 int sign[maxn],fa[maxn],n,m,k,cnt,tot;
    15 bool cmp1(Edge x,Edge y){return x.w>y.w;}
    16 bool cmp2(Edge x,Edge y){return x.w<y.w;}
    17 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    18 void kruskal(int f)
    19 {
    20     cnt=0;
    21     for(int i=1;i<=n;++i) fa[i]=i;
    22     for(int i=1;i<=m;++i){
    23         int u=e[i].u,v=e[i].v;
    24         int k1=find(u),k2=find(v);
    25         if(k1!=k2){
    26             if(f){
    27                 if(e[i].w<1){
    28                     if(tot<k) tot++;
    29                     else continue;
    30                 }
    31                 e[i].f=1;
    32             }
    33             else if(!e[i].w) continue;
    34             fa[k1]=k2;
    35             ++cnt;
    36         }
    37         if(cnt+1==n) return;
    38     }
    39 }
    40 int main()
    41 {
    42     scanf("%d%d%d",&n,&m,&k);
    43     for(int i=1;i<=m;++i) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    44     sort(e+1,e+m+1,cmp1);
    45     kruskal(0);
    46     cnt=0;
    47     for(int i=1;i<=n;++i){
    48         if(fa[i]==i){
    49             cnt++;
    50             sign[i]=1;
    51         }
    52     }
    53     if(cnt-1>k){
    54         puts("no solution");
    55         return 0;
    56     }
    57     for(int i=1;i<=m;++i) if(!e[i].w) if(sign[e[i].u]||sign[e[i].v]) e[i].w=-1;
    58     sort(e+1,e+m+1,cmp2);
    59     kruskal(1);
    60     if(cnt+1<n||tot!=k){
    61         puts("no solution");
    62         return 0;
    63     }
    64     for(int i=1;i<=m;++i) if(e[i].f) printf("%d %d %d
    ",e[i].u,e[i].v,e[i].w<1?0:1);
    65     return 0;
    66 }
  • 相关阅读:
    工作流 —— AWS
    ant design —— form 生成 嵌套json数据
    react 获取子组件的 state (转发)
    React 调用子组件的函数(函数)
    react js 组件传参(转发)
    链接脚本文件(.ld .lds)详解
    gcc ------ -ffunction-sections -fdata-sections -gc-sections 参数详解
    GNU ARM 汇编伪指令
    STM32 CM3/CM4 ------ startup.s 文件分析 ------ GCC RT-Thread Studio 版本
    __attribute__之section详解 ------ 把函数指定到具体某个section 之 RT-thread 实例详解
  • 原文地址:https://www.cnblogs.com/12mango/p/7641581.html
Copyright © 2020-2023  润新知