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. 一、CnPack源码模板功能快速添加注释

    Delphi通过CnPack源码模板功能,能快速添加注释,非常之好用,使用方法如下图: 1.选择CnPack的源码模板专家 2.设置Pacal标准过程头 3.设置内容如下,并且设置了Ctrl+W的快捷 ...

  2. MSP430F5438A的串口

    设置串口,最关键的是波特率的设置,推荐一个网站,很方便地计算波特率,http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP43 ...

  3. 《网络对抗》Exp5 MSF基础应用

    20155336<网络对抗>Exp5 MSF基础应用 一.基础知识回答 用自己的话解释什么是exploit,payload,encode exploit:渗透攻击的模块合集,将真正要负责攻 ...

  4. MFC CTreeCtrl控件

    知识点: 认识CTreeCtrl CTreeCtrl控件属性 CTreeCtrl添加根项 CTreeCtrl添加子项 一.CTreeCtrl控件属性 先设置CTreeCtrl的属性: Has Line ...

  5. Markdown之语法入门篇

    Markdown语法入门 一.什么是Markdown语言 我相信有很多小伙伴没有听说过Markdown语言.的确,对于一般人来说,有word足够了.但是有这么一群人,受够了word那糟糕的排版方式,需 ...

  6. KVM虚拟机管理——虚拟机创建和操作系统安装

    1. 概述2. 交互式安装2.1 图形化-本地安装2.1.1 图形化本地CDROM安装2.2.2 图形化本地镜像安装2.2 命令行-本地安装2.2.1 命令行CDROM安装2.3 图形化-网络安装2. ...

  7. NX 栈不可执行的绕过方式--ROP链

    目标程序下载 提取码:5o0a 环境:Ubuntu linux 工具 pwn-gdb pwntools python库 ROPgadget ( 这些工具可以到github官网找) 1.检查程序开了哪些 ...

  8. 广州区块链系统or积分联盟

    区块链技术开发至今已有十年,从概念的现世到如今初步应用,区块链开发公司在各个领域开始发光发热,很多人都想参与其中,通过区块链开发实现企业转型来适应未来市场,也有一些初创者希望借此实现创业意图,但在诸多 ...

  9. 微软职位内部推荐-Senior Program Manager

    微软近期Open的职位: Title: Senior Program Manager – Bing Multimedia Relevance Group: Search Technology Cent ...

  10. 获取apk的签名信息

    在接入第三方功能时,经常要注册提交apk的签名信息 (sha1签名)?,下面列出相关步骤. 获取apk签名信息的步骤: 1)修改apk后缀名为zip,解压得到其中的META-INF文件夹; 2)把ME ...