• 3624: [Apio2008]免费道路


    3624: [Apio2008]免费道路

    https://www.lydsy.com/JudgeOnline/problem.php?id=3624

    题意:

      一张无向图,每种边有两种类型0和1。求一个最小生成树使得有k条0边。

    分析:

      为了满足有k条0边的限制,先考虑0边哪些必选,如果所有1边都加入后,还有0边可以使得图不连通,那么这些0边必须选。

      把必须选的加上然后再加到k,然后再加1边。中间判一下是否必选的大于k,0边是否大于等于k。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 
     5 inline int read() { 
     6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     7     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     8 }
     9 
    10 const int N = 20010;
    11 const int M = 100010;
    12 
    13 struct Edge{
    14     int u,v;
    15     Edge() {}
    16     Edge(int a,int b) {u = a, v = b;}
    17 }e[M];
    18 int fa[N], q[M];
    19 bool vis[M];
    20 
    21 int find(int x) {
    22     return x == fa[x] ? x : fa[x] = find(fa[x]);
    23 }
    24 
    25 int main () {
    26     
    27     int n = read(), m = read(), k = read();
    28     
    29     int B = 0, W = m + 1;
    30     for (int i=1; i<=m; ++i) {
    31         int u = read(), v = read(), c = read();
    32         if (c == 1) e[++B] = Edge(u,v);
    33         else e[--W] = Edge(u,v);
    34     }
    35     
    36     for (int i=1; i<=n; ++i) fa[i] = i;
    37     
    38     int tot = 0;
    39     for (int i=1; i<=m; ++i) {
    40         int u = find(e[i].u), v = find(e[i].v);
    41         if (u == v) continue;
    42         fa[u] = v;
    43         if (i > B) vis[i] = true, q[++tot] = i;
    44     }
    45     
    46     if (tot > k) {
    47         puts("no solution");
    48         return 0;
    49     }
    50     
    51     for (int i=1; i<=n; ++i) fa[i] = i;
    52     
    53     for (int i=1; i<=tot; ++i) 
    54         fa[find(e[q[i]].u)] = find(e[q[i]].v);
    55     
    56     for (int i=W; i<=m; ++i) {
    57         if (tot == k) break;
    58         int u = find(e[i].u), v = find(e[i].v);
    59         if (u == v) continue;
    60         fa[u] = v;
    61         tot ++;
    62         vis[i] = true;
    63     }
    64     
    65     if (tot < k) {
    66         puts("no solution");
    67         return 0;
    68     }
    69     
    70     for (int i=1; i<=B; ++i) {
    71         int u = find(e[i].u), v = find(e[i].v);
    72         if (u == v) continue;
    73         fa[u] = v;
    74         vis[i] = true;
    75     }
    76     
    77     for (int i=1; i<=m; ++i) 
    78         if (vis[i]) printf("%d %d %d
    ", e[i].u, e[i].v, i<=B?1:0);
    79 
    80     return 0;
    81 }
  • 相关阅读:
    iso下载不完整,无论什么方式下载一定要校验md5码
    NR/NT,Taxonomy和RefSeq——三种NCBI常见数据库
    微生物群落多样性测序与功能分析
    分子伴侣
    细菌或真菌菌种鉴定中的16S rRNA,18S rRNA等
    tmRNA的结构和功能
    神秘的细菌基因组:GC skew
    由浅入深理解 IOC 和 DI
    详细分析 Java 中启动线程的正确和错误方式
    详细分析 Java 中实现多线程的方法有几种?(从本质上出发)
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9357005.html
Copyright © 2020-2023  润新知