【BZOJ3624】免费道路

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3624


 

坑!!!

先注明,输出no solution时也要换行,不换不对,别问我怎么知道的。

思路巧妙,值得学习。我们要保留k条鹅卵石路,可以优先添加水泥路,从而确定哪些鹅卵石路是必须添加的。

若添加完一遍,发现找不到n-1条边,说明图不连通,输出no solution\n;若必须添加的鹅卵石路多于k条,说明无解,输出no solution\n。

然后我们先把必须添加的鹅卵石路添加上,不足k条就优先从鹅卵石路中补上,若补不齐,说明无解,输出no solution\n。

最后输出答案即可。

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 inline int get_num() {
 7     int num = 0;
 8     char c = getchar();
 9     while (c < '0' || c > '9') c = getchar();
10     while (c >= '0' && c <= '9')
11         num = num * 10 + c - '0', c = getchar();
12     return num;
13 }
14 
15 const int maxn = 2e4 + 5, maxm = 1e5 + 5;
16 
17 struct Edge {
18     int u, v, c;
19     bool operator < (const Edge& rhs) const {
20         return c > rhs.c;
21     }
22 } edge[maxm];
23 
24 int fa[maxn], need[maxn], neid, ans[maxn], aeid;
25 
26 int dj_find(int i) {
27     if (i == fa[i]) return i;
28     else return fa[i] = dj_find(fa[i]);
29 }
30 
31 inline void dj_merge(int a, int b) {
32     fa[dj_find(a)] = dj_find(b);
33 }
34 
35 int main() {
36     int n = get_num(), m = get_num(), k = get_num();
37     for (int i = 1; i <= m; ++i) {
38         edge[i].u = get_num();
39         edge[i].v = get_num();
40         edge[i].c = get_num();
41     }
42     sort(edge + 1, edge + m + 1);
43     for (int i = 1; i <= n; ++i) fa[i] = i;
44     for (int i = 1; i <= m; ++i) {
45         int u = edge[i].u, v = edge[i].v;
46         if (dj_find(u) != dj_find(v)) {
47             dj_merge(u, v);
48             ans[++aeid] = i;
49             if (!edge[i].c) need[++neid] = i;
50         }
51     }
52     if (neid > k || aeid != n - 1) {printf("no solution\n"); return 0;}
53     for (int i = 1; i <= n; ++i) fa[i] = i;
54     aeid = 0;
55     for (int i = 1; i <= neid; ++i) {
56         int u = edge[need[i]].u, v = edge[need[i]].v;
57         dj_merge(u, v);
58         ans[++aeid] = need[i];
59     }
60     int cnt = neid;
61     for (int i = m; i >= 1; --i) {
62         if (cnt == k && !edge[i].c) continue;
63         int u = edge[i].u, v = edge[i].v;
64         if (dj_find(u) != dj_find(v)) {
65             dj_merge(u, v);
66             if (!edge[i].c) ++cnt;
67             ans[++aeid] = i;
68         }
69     }
70     if (cnt < k) {printf("no solution\n"); return 0;}
71     for (int i = 1; i <= aeid; ++i)
72         printf("%d %d %d\n", edge[ans[i]].u, edge[ans[i]].v, edge[ans[i]].c);
73     return 0;
74 }
AC代码

 

posted @ 2018-11-04 18:13  Mr^Kevin  阅读(104)  评论(0编辑  收藏  举报