BZOJ 3624: [Apio2008]免费道路 [生成树 并查集]
题意:
一张图0,1两种边,构造一个恰有k条0边的生成树
优先选择1边构造生成树,看看0边是否小于k
然后保留这些0边,补齐k条,再加1边一定能构成生成树
类似kruskal的证明
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=2e4+, M=1e5+;
typedef long long ll;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} int n, m, k, u, v, c, m0, m1, p;
struct meow{int u, v, c;}a[M], b[M], ans[N];
int fa[N];
int find(int x) {return x==fa[x] ? x : fa[x]=find(fa[x]);}
int flag[N];
int main() {
freopen("in","r",stdin);
n=read(); m=read(); k=read();
for(int i=; i<=m; i++) {
u=read(), v=read(), c=read();
if(c==) a[++m1]=(meow){u,v,c};
else b[++m0]=(meow){u,v,c};
} int cnt=;
for(int i=; i<=n; i++) fa[i]=i;
for(int i=; i<=m1; i++) {
u=a[i].u, v=a[i].v;
int x=find(u), y=find(v);
if(x==y) continue;
fa[x]=y;
if(++cnt == n-) break;
}
for(int i=; i<=m0; i++) {
u=b[i].u, v=b[i].v;
int x=find(u), y=find(v);
if(x==y) continue;
fa[x]=y; ans[++p]=b[i]; flag[i]=;
if(++cnt == n-) break;
}
if(p > k || cnt < n-) {puts("no solution"); return ;} for(int i=; i<=n; i++) fa[i]=i;
for(int i=; i<=p; i++) fa[find(ans[i].u)] = find(ans[i].v);
cnt=p;
if(cnt<k) for(int i=; i<=m0; i++) if(!flag[i]){
u=b[i].u, v=b[i].v;
int x=find(u), y=find(v);
if(x==y) continue;
fa[x]=y; ans[++cnt]=b[i];
if(cnt == k) break;
}
for(int i=; i<=m1; i++) {
u=a[i].u, v=a[i].v;
int x=find(u), y=find(v);
if(x==y) continue;
fa[x]=y; ans[++cnt]=a[i];
if(cnt == n-) break;
}
for(int i=; i<=cnt; i++) printf("%d %d %d\n",ans[i].u, ans[i].v, ans[i].c);
}
2017-10-03 今天又写了一下 以前好像有点问题洛谷wa1
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int N = 1e5+, M = 1e5+;
typedef long long ll;
inline int read() {
char c=getchar(); int x=,f=;
while(c<''||c>'') {if(c=='-')f=-;c=getchar();}
while(c>=''&&c<='') {x=x*+c-'';c=getchar();}
return x*f;
} int n, m, k;
struct edge {int u, v, c;} e[M];
int flag[N], fa[N], ans[N];
int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
int main() {
//freopen("in", "r", stdin);
scanf("%d %d %d", &n, &m, &k);
for(int i=; i<=m; i++) e[i].u = read(), e[i].v = read(), e[i].c = read(); for(int i=; i<=n; i++) fa[i] = i;
int num = ;
for(int i=; i<=m; i++) if(e[i].c == ) {
int f1 = find(e[i].u), f2 = find(e[i].v);
if(f1 == f2) continue;
fa[f1] = f2;
if(++num == n-) break;
}
int one = ;
for(int i=; i<=m; i++) if(e[i].c == ) {
int f1 = find(e[i].u), f2 = find(e[i].v);
if(f1 == f2) continue;
fa[f1] = f2;
one++; ans[++ans[]] = i; flag[i] = ;
if(++num == n-) break;
}
if(one > n-k) {puts("no solution"); return ;}
if(num < n-) {puts("no solution"); return ;} for(int i=; i<=n; i++) fa[i] = i;
num = ;
for(int i=; i<=m; i++) if(e[i].c == ) {
int f1 = find(e[i].u), f2 = find(e[i].v);
if(f1 == f2) continue;
fa[f1] = f2;
if(++num == n-) break;
}
int zero = ;
for(int i=; i<=m; i++) if(e[i].c == ) {
int f1 = find(e[i].u), f2 = find(e[i].v);
if(f1 == f2) continue;
fa[f1] = f2;
zero++; ans[++ans[]] = i; flag[i] = ;
if(++num == n-) break;
}
if(zero > k) {puts("no solution"); return ;} for(int i=; i<=n; i++) fa[i] = i;
num = ans[];
for(int i=, t; i<=ans[]; i++) t = ans[i], fa[find(e[t].u)] = find(e[t].v);
if(zero < k) for(int i=; i<=m; i++) if(!flag[i] && e[i].c == ) {
int f1 = find(e[i].u), f2 = find(e[i].v);
if(f1 == f2) continue;
fa[f1] = f2;
ans[++ans[]] = i;
++num;
if(++zero == k) break;
}
if(num < n-) for(int i=; i<=m; i++) if(!flag[i] && e[i].c == ) {
int f1 = find(e[i].u), f2 = find(e[i].v);
if(f1 == f2) continue;
fa[f1] = f2;
ans[++ans[]] = i;
if(++num == n-) break;
} if(zero != k || num != n-) {puts("no solution"); return ;}
for(int i=, t; i<=ans[]; i++) t = ans[i], printf("%d %d %d\n", e[t].u, e[t].v, e[t].c);
}
BZOJ 3624: [Apio2008]免费道路 [生成树 并查集]的更多相关文章
- BZOJ 3624 [Apio2008]免费道路:并查集 + 生成树 + 贪心【恰有k条特殊路径】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3624 题意: 给你一个无向图,n个点,m条边. 有两种边,种类分别用0和1表示. 让你求一 ...
- bzoj 3624: [Apio2008]免费道路 生成树的构造
3624: [Apio2008]免费道路 Time Limit: 2 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 111 Solved: 4 ...
- BZOJ 3624: [Apio2008]免费道路
3624: [Apio2008]免费道路 Time Limit: 2 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 1201 Solved: ...
- bzoj 3624: [Apio2008]免费道路【生成树+贪心】
先把水泥路建生成树,然后加鹅卵石路,这里加的鹅卵石路是一定要用的(连接各个联通块),然后初始化并查集,先把必需的鹅卵石路加进去,然后随便加鹅卵石路直到k条,然后加水泥路即可. 注意判断无解 #incl ...
- Bzoj 3624: [Apio2008]免费道路 (贪心+生成树)
Sample Input 5 7 2 1 3 0 4 5 1 3 2 0 5 3 1 4 3 0 1 2 1 4 2 1 Sample Output 3 2 0 4 3 0 5 3 1 1 2 1 这 ...
- BZOJ.3624.[APIO2008]免费道路(Kruskal)
题目链接 我们发现有些白边是必须加的,有些是多余的. 那么我们先把所有黑边加进去,然后把必须要加的白边找出来. 然后Kruskal,把必须要加的白边先加进去,小于K的话再加能加的白边.然后加黑边. 要 ...
- [APIO2008]免费道路(生成树)
新亚(New Asia)王国有 N 个村庄,由 M 条道路连接.其中一些道路是鹅卵石路,而其它道路是水泥路.保持道路免费运行需要一大笔费用,并且看上去 王国不可能保持所有道路免费.为此亟待制定一个新的 ...
- 3624: [Apio2008]免费道路
Description Input Output Sample Input 5 7 2 1 3 0 4 5 1 3 2 0 5 3 1 4 3 0 1 2 1 4 2 1 Sample Output ...
- [Apio2008]免费道路[Kruscal]
3624: [Apio2008]免费道路 Time Limit: 2 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 1292 Solved: ...
随机推荐
- cesium编程入门(五)绘制形状
通过Entity添加形状 先来看一个添加立方体的例子 var viewer = new Cesium.Viewer('cesiumContainer'); var redBox = **viewer. ...
- java如何获取一个对象的大小
When---什么时候需要知道对象的内存大小 在内存足够用的情况下我们是不需要考虑java中一个对象所占内存大小的.但当一个系统的内存有限,或者某块程序代码允许使用的内存大小有限制,又或者设计一个缓存 ...
- IDC服务器的六大基础知识
无论企业或个人来说,一个是否适合自己的IDC运营商对于业务发展是至关重要的.然而很多用户对IDC行业一知半解,不太了解服务器的种类,更不知道选择什么样的服务器更适合自己了.今天编辑汇总了一些IDC所需 ...
- Ajax beforeSend和complete 方法
http://blog.csdn.net/chenjianandiyi/article/details/52274591 .ajax({ beforeSend: function(){ // Hand ...
- ADO.NET复习总结(3)--参数化SQL语句--防止sql注入式攻击
1.SQL 注入 2.使用参数化的方式,可以有效防止SQL注入,使用类parameter的实现类SqlParameter Command的属性parameters是一个参数集合. 3.举例<查询 ...
- asp.net -mvc框架复习(4)-ASP.NET MVC中的约定规则
1.路由规则 using System;using System.Collections.Generic;using System.Linq;using System.Web;using System ...
- 改变UITableView选中行高亮的颜色
UIView *backView = [[UIView alloc] initWithFrame:self.contentView.frame]; backView.backgroundColor = ...
- linux mysql 修改 UTF-8编码
版本大于5.5 [mysqld]下添加的应该为: character-set-server=utf8 collation-server=utf8_general_ci 版本小于5.5 [cli ...
- java中String的.trim()方法
该方法去除两边的空白符 原理: 看看源码实现 public String trim() { int len = value.length; ; char[] val = value; /* avoid ...
- 网络编程之TCP编程
网络编程之TCP编程 前面已经介绍过关于TCP协议的东西,这里不做赘述.Java对于基于TCP协议的网络通信提供了良好的封装,Java使用socket对象来代表两端的通信窗口,并通过Socket产生I ...