【luogu P3623 [APIO2008]免费道路】 题解
题目链接:https://www.luogu.org/problemnew/show/P3623
说是对克鲁斯卡尔的透彻性理解
正解:
先考虑加入水泥路,然后再考虑加入剩下必须要加入的最少鹅卵石路。
之后对原图再跑最小生成树
先跑鹅卵石路到k条。
再从所有水泥路中直到成为最小生成树。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100000 + 10;
int n, m, k, fa[maxn], cnt, shuini, eluan, tot;
bool f[maxn];
struct edge{
int u, v, w;
}e[maxn<<2], ans[maxn<<2];
bool cmp(edge a, edge b)
{
return a.w < b.w;
}
int find(int x)
{
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i = 1; i <= n; i++) fa[i] = i;
for(int i = 1; i <= m; i++)
{
int opt;
scanf("%d%d%d",&e[i].u, &e[i].v, &opt);
if(opt == 0) e[i].w = 1, eluan++;
else e[i].w = 0, shuini++;
}
if(eluan < k)
{
cout<<"no solution\n";
return 0;
}
sort(e+1, e+1+m, cmp);
for(int i = 1; i <= shuini; i++)
{
if(cnt == n-1) break;
int rx, ry;
rx = find(e[i].u), ry = find(e[i].v);
if(rx != ry)
{
fa[ry] = rx;
cnt++;
}
}
int eluanmust = 0;
for(int i = shuini+1; i <= m; i++)
{
if(cnt == n-1) break;
int rx, ry;
rx = find(e[i].u), ry = find(e[i].v);
if(rx != ry)
{
fa[ry] = rx;
f[i] = 1, eluanmust++;
cnt++;
}
}
if(cnt != n-1 || eluanmust > k)
{
cout<<"no solution\n";
return 0;
}
for(int i = 1; i <= n; i++) fa[i] = i;
cnt = 0;
for(int i = shuini+1; i <= m; i++)
{
if(cnt == n-1) break;
if(f[i] == 1)
{
int rx, ry;
rx = find(e[i].u), ry = find(e[i].v);
fa[ry] = rx;
cnt++;
ans[++tot].u = e[i].u;
ans[tot].v = e[i].v;
ans[tot].w = e[i].w^1;
//printf("%d %d %d\n",e[i].u, e[i].v, e[i].w^1);
}
}
for(int i = shuini+1; i <= m; i++)
{
if(cnt == k) break;
int rx, ry;
rx = find(e[i].u), ry = find(e[i].v);
if(rx != ry)
{
fa[ry] = rx;
cnt++;
ans[++tot].u = e[i].u;
ans[tot].v = e[i].v;
ans[tot].w = e[i].w^1;
//printf("%d %d %d\n",e[i].u, e[i].v, e[i].w^1);
}
}
if(cnt < k)
{
cout<<"no solution\n";
return 0;
}
for(int i = 1; i <= shuini; i++)
{
if(cnt == n-1) break;
int rx, ry;
rx = find(e[i].u), ry = find(e[i].v);
if(rx != ry)
{
fa[ry] = rx;
cnt++;
ans[++tot].u = e[i].u;
ans[tot].v = e[i].v;
ans[tot].w = e[i].w^1;
//printf("%d %d %d\n",e[i].u, e[i].v, e[i].w^1);
}
}
if(cnt != n-1)
{
cout<<"no solution\n";
return 0;
}
for(int i = 1; i <= tot; i++)
printf("%d %d %d\n",ans[i].u, ans[i].v, ans[i].w);
return 0;
}
【luogu P3623 [APIO2008]免费道路】 题解的更多相关文章
- [火星补锅] 水题大战Vol.2 T2 && luogu P3623 [APIO2008]免费道路 题解
前言: 如果我自己写的话,或许能想出来正解,但是多半会因为整不出正确性而弃掉. 解析: 这题算是对Kruskal的熟练运用吧. 要求一颗生成树.也就是说,最后的边数是确定的. 首先我们容易想到一个策略 ...
- 题解 Luogu P3623 [APIO2008]免费道路
[APIO2008]免费道路 题目描述 新亚(New Asia)王国有 N 个村庄,由 M 条道路连接.其中一些道路是鹅卵石路,而其它道路是水泥路.保持道路免费运行需要一大笔费用,并且看上去 王国不可 ...
- P3623 [APIO2008]免费道路
3624: [Apio2008]免费道路 Time Limit: 2 Sec Memory Limit: 128 MBSec Special Judge Submit: 2143 Solved: 88 ...
- [BZOJ3624][Apio2008]免费道路
[BZOJ3624][Apio2008]免费道路 试题描述 输入 输出 输入示例 输出示例 数据规模及约定 见“输入”. 题解 第一步,先尽量加入 c = 1 的边,若未形成一个连通块,则得到必须加入 ...
- [APIO2008]免费道路
[APIO2008]免费道路 BZOJ luogu 先把必须连的鹅卵石路连上,大于k条no solution 什么样的鹅卵石路(u,v)必须连?所有水泥路都连上仍然不能使u,v连通的必须连 补全到k条 ...
- 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: ...
- [Apio2008]免费道路[Kruscal]
3624: [Apio2008]免费道路 Time Limit: 2 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 1292 Solved: ...
- Kruskal算法及其类似原理的应用——【BZOJ 3654】tree&&【BZOJ 3624】[Apio2008]免费道路
首先让我们来介绍Krukal算法,他是一种用来求解最小生成树问题的算法,首先把边按边权排序,然后贪心得从最小开始往大里取,只要那个边的两端点暂时还没有在一个联通块里,我们就把他相连,只要这个图里存在最 ...
随机推荐
- Servlet开发(三)之ServletConfig,ServletContext
1. ServletConfig Servlet是开发动态web的技术,而web.xml是Tomcat工程中最基础也最重要的配置文件,Tomcat启动项目的时候会加载并读取这个文件,其中web.xml ...
- so模块加载后数据问题
lualib-src里面都没有存数据的地方 那么bjm里面的这块数据防全局,再多个虚拟机里require后数据会全局共享吗
- html 之 position用法
引用: position的四个属性值: 1.relative2.absolute3.fixed4.static下面分别讲述这四个属性. <div id="parent"> ...
- elentment-ui解析
序言 现在前端的技术越来越杂,也越来越细了,以至于每次看完文档都会有个错觉,就是自己差不多会了.真正去做项目的时候又是重复之前的步骤. 之前写Java的时候,会习惯性的看看源码,看完之后会对知识掌握的 ...
- 实现绘制图形的ToolBar
给地图添加绘制图形的ToolBar还是有必要的,比较人性化的功能.图形的样式可以自己定制,也提供了朴实的默认样式.对 dojo 不太懂,出现了许许多多问题,真是蛋疼的一天啊.令人惊喜的是 ArcGis ...
- C++基础--回调的应用
一.类成员函数的回调 1. 类成员函数的回调,函数的调用必须通过类来调用: CallBack.h #pragma once class CallBack { public: CallBack(); ~ ...
- c++实现对输入数组进行快速排序
#include "stdafx.h" #include <iostream> #include <string> #include <vector& ...
- CefSharp开发
CefSharp是用chromium内核开发的.net版本浏览器工具.目前只支持X86模式.所以在调试的时候要把平台改为X86 CefSharp开发指引:https://ourcodeworld.co ...
- ssh_exchange_identification: Connection closed by remote host
用服务器内网ip连接同子网服务器的时候显示ssh_exchange_identification: Connection closed by remote host 防火墙什么都关闭了,还是显示这个问 ...
- Python学习---重点模块之configparse
configparse模块常用于生成和修改常见的配置文档 生成配置模块:用字典写 import configparser config = configparser.ConfigParser() co ...