题意:

一张图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]免费道路 [生成树 并查集]的更多相关文章

  1. BZOJ 3624 [Apio2008]免费道路:并查集 + 生成树 + 贪心【恰有k条特殊路径】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3624 题意: 给你一个无向图,n个点,m条边. 有两种边,种类分别用0和1表示. 让你求一 ...

  2. bzoj 3624: [Apio2008]免费道路 生成树的构造

    3624: [Apio2008]免费道路 Time Limit: 2 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 111  Solved: 4 ...

  3. BZOJ 3624: [Apio2008]免费道路

    3624: [Apio2008]免费道路 Time Limit: 2 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1201  Solved:  ...

  4. bzoj 3624: [Apio2008]免费道路【生成树+贪心】

    先把水泥路建生成树,然后加鹅卵石路,这里加的鹅卵石路是一定要用的(连接各个联通块),然后初始化并查集,先把必需的鹅卵石路加进去,然后随便加鹅卵石路直到k条,然后加水泥路即可. 注意判断无解 #incl ...

  5. 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 这 ...

  6. BZOJ.3624.[APIO2008]免费道路(Kruskal)

    题目链接 我们发现有些白边是必须加的,有些是多余的. 那么我们先把所有黑边加进去,然后把必须要加的白边找出来. 然后Kruskal,把必须要加的白边先加进去,小于K的话再加能加的白边.然后加黑边. 要 ...

  7. [APIO2008]免费道路(生成树)

    新亚(New Asia)王国有 N 个村庄,由 M 条道路连接.其中一些道路是鹅卵石路,而其它道路是水泥路.保持道路免费运行需要一大笔费用,并且看上去 王国不可能保持所有道路免费.为此亟待制定一个新的 ...

  8. 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 ...

  9. [Apio2008]免费道路[Kruscal]

    3624: [Apio2008]免费道路 Time Limit: 2 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1292  Solved:  ...

随机推荐

  1. ZOJ 1002 DFS

    Fire Net Time Limit: 2 Seconds      Memory Limit: 65536 KB Suppose that we have a square city with s ...

  2. poj_2195Going Home(最小费用最大流)

    poj_2195Going Home(最小费用最大流) 标签: 最小费用最大流 题目链接 题意: 有n*m的矩阵,H表示这个点是一个房子,m表示这个点是一个人,现在每一个人需要走入一个房间,已经知道的 ...

  3. 南阳理工oj_The Triangle

    The Triangle 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (Figure 1) Figure 1 ...

  4. A very hard Aoshu problem(dfs或者数位)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4403 A very hard Aoshu problem Time Limit: 2000/1000 ...

  5. 数值积分之Simpson公式与梯形公式

    Simpson(辛普森)公式和梯形公式是求数值积分中很重要的两个公式,可以帮助我们使用计算机求解数值积分,而在使用过程中也有多种方式,比如复合公式和变步长公式.这里分别给出其简单实现(C++版): 1 ...

  6. ubuntu下使用nginx搭建流媒体服务器,实现视频点播

    首先我们看如何实现视频点播,视频点播支持flv文件及H264编码视频,ACC编码音频的mp4文件: 第一步,创建单独的目录(因为软件较多,容易混乱),下载需要的软件: 我们需要下载nginx,pcre ...

  7. [国嵌攻略][070][GDB调试程序]

    GDB是GNU发布的一款功能强大的调试工具.GDB主要完成下面三个方面的功能: 1.启动被调试的程序. 2.让被调试的程序在指定的位置停住. 3.当程序被停住时,可以检测程序状态. GDB使用流程 1 ...

  8. Entity framework 中Where、First、Count等查询函数使用时要注意

    在.Net开发中,Entity framework是微软ORM架构的最佳官方工具.我们可以使用Lambda表达式在Entity framework中DbSet<T>类上直接做查询(比如使用 ...

  9. AMD规范学习笔记

    背景 NodeJS的一套比较简洁 Moudles 规范, 使得在服务器端的模块化变得更加简单.很长一段时间,很多公司或者项目都有自己的一套模块化机制, 却未能形成一套统一的标准, NodeJS的Mou ...

  10. 番外篇--Moddule Zero介绍

    1.1 ABPZero - 概述 介绍 微软ASP.NET身份框架 权限 会话 角色管理 默认角色 用户管理 多租户 设置管理 审计日志 1.1.1 介绍 Modulde Zero实现了ASP.NET ...