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 }