3624: [Apio2008]免费道路

Time Limit: 2 Sec  Memory Limit: 128 MBSec  Special Judge
Submit: 1201  Solved: 469
[Submit][Status][Discuss]

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

3 2 0
4 3 0
5 3 1
1 2 1

HINT

 

Source

 

[Submit][Status][Discuss]

哎呀,这题好气啊,明明不难的,就是想不到啊,还是我太蒟蒻了啊。

题意要求我们求出一棵生成树,但是这次限制的不是权值大小,而是在一个给定的边集的子集中选出恰好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]免费道路的更多相关文章

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

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

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

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

  3. BZOJ 3624: [Apio2008]免费道路 [生成树 并查集]

    题意: 一张图0,1两种边,构造一个恰有k条0边的生成树 优先选择1边构造生成树,看看0边是否小于k 然后保留这些0边,补齐k条,再加1边一定能构成生成树 类似kruskal的证明 #include ...

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

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

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

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

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

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

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

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

  9. P3623 [APIO2008]免费道路

    3624: [Apio2008]免费道路 Time Limit: 2 Sec Memory Limit: 128 MBSec Special Judge Submit: 2143 Solved: 88 ...

随机推荐

  1. Debuggex – 超好用的正则表达式可视化调试工具

    正则表达式通常被用来检索或替换符合某个模式的文本内容,编写正则是开发人员的必备技能.简单的正则表达式一下就能看懂含义,但是复杂的正则理解起来就很困难了.有了这款可视化的正则调试工具,以后编写正则表达式 ...

  2. jQuery上传文件

    1.引入资源 <script src="/yami/backend/backres/js/jquery.min.js"></script> <scri ...

  3. 避免代码merge后无法构建发布(GItlabCI + Jenkins)

    1.准备工作 目标: 开发人员提交代码后触发GitlabCI ,如果有merge请求则触发Jenkins对源分支在开发环境构建测试. 2.GItlab配置 开启仅允许pipeline成功后才能merg ...

  4. go语言之行--文件操作、命令行参数、序列化与反序列化详解

    一.简介 文件操作对于我们来说也是非常常用的,在python中使用open函数来对文件进行操作,而在go语言中我们使用os.File对文件进行操作. 二.终端读写 操作终端句柄常量 os.Stdin: ...

  5. PHP7添加opcache.so模块

    启动php报错如下: # /usr/local/php7/sbin/php-fpm [-Apr- ::] NOTICE: PHP message: PHP Warning: PHP Startup: ...

  6. 大话Java中的哈希(hash)结构(一)

    o( ̄▽ ̄)d 小伙伴们在上网或者搞程序设计的时候,总是会听到关于“哈希(hash)”的一些东西.比如哈希算法.哈希表等等的名词,那么什么是hash呢? 一.相关概念 1.hash算法:一类特殊的算法 ...

  7. kubernetes(k8s) 的常用命令

    1.查询副本[root@master ~]# kubectl get pods2.删除一个副本[root@master ~]# kubectl get pods 3.启动一个容器副本[root@mas ...

  8. 使用Windows Server 2003搭建一个asp+access网站

    鼠标右键->新建->网站->下一步->描述(随便给一个,这里我以test为例) ->下一步->下一步->输入主目录的路径,默认路径下是C:\Inetpub\w ...

  9. Unity2D 面向目标方向

    在2d空间上,假设角色的自身的y轴方向为正方向,如果要让角色随时面向一个目标点. 这里假设(0,0)点为目标点 第一种: Vector3 v = Vector3.zero - transform.po ...

  10. [T-ARA][결혼 하지마][不要结婚]

    歌词来源:http://music.163.com/#/song?id=27808773 作曲 : 二段横踢 [作曲 : 二段横踢] 作词 : 二段横踢 [作词 : 二段横踢] Hey anybody ...