bzoj3624: [Apio2008]免费道路

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3624: [Apio2008]免费道路相关的知识,希望对你有一定的参考价值。

具体题目:https://vjudge.net/problem/HYSBZ-3624

 

Description

一个王国有N个城市和M条无向道路,这M条道路中有一些是鹅卵石路一些是水泥路。现在国王要选择尽可能少的路免费,并且使每两个城市都有一条免费路径。国王打算保留刚好K条鹅卵石路。请问国王是否可以办到所有这些要求,如果能则输出路径的两个城市和路的种类,否则”no solution”。

 

HINT
N <= 20000
M <= 100000

 

Analysis
如果能成功肯定是最小生成树。
做法是把kruskal变形一下。
先连所有的水泥路,然后连接鹅卵石路就可以得到哪些鹅卵石路是必须使用的(如果超过K直接no solution),然后按kruskal连鹅卵石路直到K条(如果连不到直接no solution),然后继续按照kruskal连水泥路。

 

吐槽:文末必须换行(WA了将近20发)。

 

code

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cctype>
  4 using namespace std;
  5 const int maxn = 20020;
  6 const int maxm = 100010;
  7 int n, m, k, fat[maxn], cnt0, cnt1, num;
  8 bool chs[maxm];
  9 struct edge
 10 {
 11     int u, v, c;
 12 } e[maxm];
 13 
 14 inline int readint()
 15 {
 16     char c = getchar();
 17     while (!isdigit(c)) c = getchar();
 18     int x = 0;
 19     while (isdigit(c))
 20     {
 21         x = x * 10 + c - 0;
 22         c = getchar();
 23     }
 24     return x;
 25 }
 26 
 27 int unionset(int u)
 28 {
 29     return fat[u] == u ? u : fat[u] = unionset(fat[u]);
 30 }
 31 
 32 int main()
 33 {
 34     n = readint();
 35     m = readint();
 36     k = readint();
 37     for (int i = 1; i <= n; ++i) fat[i] = i;
 38     for (int i = 1; i <= m; ++i)
 39     {
 40         e[i].u = readint();
 41         e[i].v = readint();
 42         e[i].c = readint();
 43     }
 44     for (int i = 1; i <= m; ++i)
 45     {
 46         if (e[i].c == 1)
 47         {
 48             int r1 = unionset(e[i].u);
 49             int r2 = unionset(e[i].v);
 50             if (r1 != r2)
 51             {
 52                 fat[r1] = r2;
 53                 ++cnt1;
 54             }
 55         }
 56     }
 57     for (int i = 1; i <= m; ++i)
 58     {
 59         if (e[i].c == 0)
 60         {
 61             int r1 = unionset(e[i].u);
 62             int r2 = unionset(e[i].v);
 63             if (r1 != r2)
 64             {
 65                 chs[i] = true;
 66                 fat[r1] = r2;
 67                 ++cnt0;
 68             }
 69         }
 70     }
 71     if (cnt0 + cnt1 != n - 1 || cnt0 > k)
 72     {
 73         printf("no solution\n");
 74         return 0;
 75     }
 76     for (int i = 1; i <= n; ++i) fat[i] = i;
 77     cnt0 = cnt1 = 0;
 78     for (int i = 1; i <= m; ++i)
 79     {
 80         if (chs[i])
 81         {
 82             int r1 = unionset(e[i].u);
 83             int r2 = unionset(e[i].v);
 84             if (r1 != r2)
 85             {
 86                 fat[r1] = r2;
 87                 ++cnt0;
 88             }
 89         }
 90     }
 91     for (int i = 1; i <= m; ++i)
 92     {
 93         if (e[i].c == 0 && cnt0 < k)
 94         {
 95             int r1 = unionset(e[i].u);
 96             int r2 = unionset(e[i].v);
 97             if (r1 != r2)
 98             {
 99                 chs[i] = true;
100                 fat[r1] = r2;
101                 ++cnt0;
102             }
103         }
104     }
105     if (cnt0 != k)
106     {
107         printf("no solution\n");
108         return 0;
109     }
110     for (int i = 1; i <= m; ++i)
111     {
112         if (e[i].c == 1)
113         {
114             int r1 = unionset(e[i].u);
115             int r2 = unionset(e[i].v);
116             if (r1 != r2)
117             {
118                 chs[i] = true;
119                 fat[r1] = r2;
120             }
121         }
122     }
123     for (int i = 1; i <= m; ++i)
124         if (chs[i])
125             printf("%d %d %d\n", e[i].u, e[i].v, e[i].c);
126     return 0;
127 }

 

以上是关于bzoj3624: [Apio2008]免费道路的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3624: [Apio2008]免费道路

bzoj3624Apio2008—免费道路

Bzoj 3624: [Apio2008]免费道路 (贪心+生成树)

BZOJ 3624: [Apio2008]免费道路 [生成树 并查集]

Kruskal+贪心思想BZOJ3624-[Apio2008]免费道路

BZOJ 3624 [Apio2008]免费道路:并查集 + 生成树 + 贪心恰有k条特殊路径