BZOJ 3624: [Apio2008]免费道路
3624: [Apio2008]免费道路
Time Limit: 2 Sec Memory Limit: 128 MBSec Special Judge
Submit: 1201 Solved: 469
[Submit][Status][Discuss]
Description

Input

Output

Sample Input
1 3 0
4 5 1
3 2 0
5 3 1
4 3 0
1 2 1
4 2 1
Sample Output
4 3 0
5 3 1
1 2 1
HINT
Source
哎呀,这题好气啊,明明不难的,就是想不到啊,还是我太蒟蒻了啊。
题意要求我们求出一棵生成树,但是这次限制的不是权值大小,而是在一个给定的边集的子集中选出恰好K条边加入生成树,输出任意一种方案即可,SPJ。
这个其实很简单,你就先紧着子集里的边加,做Kruskal,求出一棵生成树(也许只能做出一棵生成森林),这是你保证了子集中选出的边>=K(如果小于K那就是无解啦),这时先用子集外的边填补漏洞,把森林补成树(补不成就是无解啦),然后再不断尝试加入子集外的边,显然加入之后会有环,那么替换掉环上的一条子集边即可(如果环上有的话),这个用LCT维护就好了,反正N<=20000是吧。
其实上面只是开玩笑的,如果你真的像我一开始这么想,看到Time Limit你就绝望了,23333——手动滑稽
正解是先紧着子集外的边加,造一个森林(能是树最好啦),然后用子集内的边补上不连通的位置。如果不能补成树或使用的子集边>K,那么就是无解。那么此时用来填补非子集边无法做到的联通性的边(就是刚才选出来的子集边)是一定要选的(并非必须边,但是一定存在一组可行解包含它们)。那么先选上这些,下面我们一定可以用非子集边把图连成生成树了,但是可能子集边还不到K,那就再随便选几个啦,然后再用非子集填补空缺。
#include <cstdio> const int mxn = ;
const int mxm = ; int n, m, k; struct edge
{
int x, y, c;
}e[mxm]; int fa[mxn]; int find(int u)
{
return u == fa[u] ? u : fa[u] = find(fa[u]);
} bool vis[mxm]; signed main(void)
{
scanf("%d%d%d", &n, &m, &k); for (int i = ; i <= m; ++i)
scanf("%d%d%d",
&e[i].x,
&e[i].y,
&e[i].c); bool possible = true; {
int cnt = , root; for (int i = ; i <= n; ++i)fa[i] = i; for (int i = ; i <= m; ++i)
if (e[i].c)
{
int fx = find(e[i].x);
int fy = find(e[i].y); if (fx != fy)
fa[fx] = fy;
} for (int i = ; i <= m; ++i)
if (!e[i].c)
{
int fx = find(e[i].x);
int fy = find(e[i].y); if (fx != fy)
fa[fx] = fy, ++cnt, vis[i] = true;
} if (cnt > k)
possible = false; root = find(); for (int i = ; i <= n; ++i)
if (find(i) != root)
possible = false; k -= cnt;
} if (!possible)
return puts("no solution"), ; {
for (int i = ; i <= n; ++i)fa[i] = i; for (int i = ; i <= m; ++i)
if (vis[i])
{
int fx = find(e[i].x);
int fy = find(e[i].y); fa[fx] = fy;
} for (int i = ; i <= m; ++i)
if (!e[i].c && !vis[i] && k)
{
int fx = find(e[i].x);
int fy = find(e[i].y); if (fx != fy)
fa[fx] = fy, vis[i] = true, --k;
} for (int i = ; i <= m; ++i)
if (e[i].c)
{
int fx = find(e[i].x);
int fy = find(e[i].y); if (fx != fy)
fa[fx] = fy, vis[i] = true;
}
} for (int i = ; i <= m; ++i)
if (vis[i])printf("%d %d %d\n", e[i].x, e[i].y, e[i].c);
}
@Author: YouSiki
BZOJ 3624: [Apio2008]免费道路的更多相关文章
- bzoj 3624: [Apio2008]免费道路 生成树的构造
3624: [Apio2008]免费道路 Time Limit: 2 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 111 Solved: 4 ...
- BZOJ 3624 [Apio2008]免费道路:并查集 + 生成树 + 贪心【恰有k条特殊路径】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3624 题意: 给你一个无向图,n个点,m条边. 有两种边,种类分别用0和1表示. 让你求一 ...
- BZOJ 3624: [Apio2008]免费道路 [生成树 并查集]
题意: 一张图0,1两种边,构造一个恰有k条0边的生成树 优先选择1边构造生成树,看看0边是否小于k 然后保留这些0边,补齐k条,再加1边一定能构成生成树 类似kruskal的证明 #include ...
- BZOJ.3624.[APIO2008]免费道路(Kruskal)
题目链接 我们发现有些白边是必须加的,有些是多余的. 那么我们先把所有黑边加进去,然后把必须要加的白边找出来. 然后Kruskal,把必须要加的白边先加进去,小于K的话再加能加的白边.然后加黑边. 要 ...
- 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 这 ...
- 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: ...
- P3623 [APIO2008]免费道路
3624: [Apio2008]免费道路 Time Limit: 2 Sec Memory Limit: 128 MBSec Special Judge Submit: 2143 Solved: 88 ...
随机推荐
- VBA读取、增加自定义和修改文档属性
读取系统文档属性 Sub read()On Error Resume Nextrw = 1Worksheets(1).ActivateFor Each p In ActiveWorkbook.Buil ...
- Scala_数据类型
Scala与Java有着相同的数据类型,Scala数据类型都是对象,Scala中没有类似Java中那样的原始类型. Scala 的基本数据类型有: Byte,Short,Int,Long 和 Char ...
- 20155233 Exp1 PC平台逆向破解(5)M
Exp1 PC平台逆向破解(5)M 实践一 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数. 步骤 1.cp pwn1 pwn20155233拷贝pwn1文件,命名为pwn201 ...
- 使用HibernateDaoSupport抽取BaseDao
在开发采用Struts2+Spring+hibernate这三大框架的项目时,我们需要一个抽取一个BaseDao.这个Dao里面CRUD都给封装好,后续的其他Dao直接用它的功能就可以 ...
- VS编程,WPF中,获取鼠标相对于当前屏幕坐标的一种方法
原文:VS编程,WPF中,获取鼠标相对于当前屏幕坐标的一种方法 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/det ...
- 《Flask Web开发实战:入门、进阶与原理解析(李辉著 )》PDF+源代码
一句话评价: 这可能是市面上(包括国外出版的)你能找到最好的讲Flask的书了 下载:链接: https://pan.baidu.com/s/1ioEfLc7Hc15jFpC-DmEYBA 提取码: ...
- POJ3278&&1426&&3126&&3087&&3414
接上次的,标签是BFS专题 其实无论是Deepth还是Breadth都是Search 3278 又是撸过的题目 1426 找一个十进制数(我刚开始看样例以为是二进制数),使得它每一位上都是1或0,且是 ...
- bodymovin实现将AE动画转换成HTML5动画
做一个简单的记录,直接贴代码吧,主要还是设计师提供的那个json <!DOCTYPE html> <html> <head> <style> body ...
- 阿里云ECS 固定带宽变为按量付费的方式
阿里云ECS 固定带宽变为按量付费的方式 阿里云控制台 2.升降配置-降低配置-降低至最低配置 3.为按量带宽设置一个峰值,例如100M. 4.过几分钟,就自动变为按量付费的带宽了.
- 在nodejs中引进模块要经历的步骤
在nodejs中引入模块需要经历如下3个步骤 1.路径分析 2.文件定位 3.编译执行 在nodejs中模块分为两类,一类是nodejs提供的模块,称为核心模块,另一类的用户编写的模块,称为文件模块. ...