【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 }