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\n", e[i].u, e[i].v, i<=B?1:0);
79 
80     return 0;
81 }

 

posted @ 2018-07-23 22:45  MJT12044  阅读(218)  评论(1编辑  收藏  举报