bzoj3624: [Apio2008]免费道路
[TOC]
#题目链接
bzoj3624: [Apio2008]免费道路
#题解
两边kruskal分别找出必须保留的石子路和软石路
剩下的随便填满k就ok了
#代码
#include<map>
#include<vector>
#include<cstdio>
#include<algorithm>
#define gc getchar()
#define pc putchar
inline int read() {
int x = 0,f = 1;
char c = gc;
while(c < '0' || c > '9')c = gc;
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = gc;
return x * f;
}
void print(int x) {
if(x < 0) {
pc('-');
x = -x;
}
if(x >= 10) print(x / 10);
pc(x % 10 + '0');
}
const int maxn = 2000007;
int a[maxn];
int n,m,k;
struct node {
int u,v,w,tag;
} e[maxn];
int num = 0;
int fa[maxn];
inline void add(int a,int b,int c) {
e[++ num].u = a,e[num].v = b; e[num].w = c;
}
inline bool c1(node a,node b) {
return a.w < b.w;
}
inline bool c2(node a,node b) {
return a.w > b.w;
}
int find(int x) {
if(x != fa[x]) fa[x] = find(fa[x]);
return fa[x];
}
int main() {
n = read(),m = read(),k = read();
for(int u,v,w,i = 1;i <= m;++ i) {
u = read(),v = read(),w = read();
add(u,v,w);
}
for(int i = 1;i <= n;++ i) fa[i] = i;
std::sort(e + 1,e + m + 1,c2);
int cnt = 0;
for(int i = 1;i <= m;++ i) {
int fx = find(e[i].u),fy = find(e[i].v);
if(fx != fy) {
fa[fx] = fy;
if(!e[i].w) e[i].tag = 1,cnt ++;
}
}
if(cnt > k) {
puts("no solution");
return 0;
}
for(int i = 1;i <= n;++ i) fa[i] = i;
for(int i = 1;i <= m;++ i)
if(e[i].tag) fa[find(e[i].u)] = fa[find(e[i].v)];
std::sort(e + 1,e + m + 1,c1) ;
for(int i = 1;i <= m;++ i) {
if(e[i].w) break;
int fx = find(e[i].u),fy = find(e[i].v);
if(fx != fy) {
fa[fx] = fy;
++ cnt;
e[i].tag = 1;
}
if(cnt == k) break;
}
if(cnt < k) {
puts("no solution");
return 0;
}
std::sort(e + 1,e + m + 1,c2);
for(int i = 1;i <= m;++ i) {
if(!e[i].w) break;
int fx = find(e[i].u),fy = find(e[i].v);
if(fx != fy) {
fa[fx] = fy;
e[i].tag = 1;
}
}
for(int i = 1;i <= m;++ i)
if(e[i].tag) {
print(e[i].u);pc(' ');
print(e[i].v);pc(' ');
print(e[i].w);pc('\n');
}
return 0;
}