题意

题目链接

Sol

首先答案一定是一棵树

这棵树上有一些0边是必须要选的,我们先把他们找出来,如果数量$\geqslant k$显然无解

再考虑继续往里面加0的边,判断能否加到k条即可

具体做法是:

先让1在前做生成树,其中加入的0边是必须要选的

再让0边在前做生成树,这时候我们不必考虑最后能否生成一棵树,只需要考虑能否加入k条即可

我的思路:首先必选的0边是一定要统计出来的,然后一次性把剩下的所有0边都加进去,显然其中会有很多没有用,如果加入的边数量$<k$则无解,

否则考虑删除一些0边,LCT维护形成环后每个环上0边的数量,如果环上0的数量$>0$则减一,把该1边加入,否则不加入。如果总的0边数量为k,

直接不断加剩下的边,最后判断能否形成一棵树,否则0边的数量>k,证明无解。

应该是对的吧,不过打死我也不会去写的。。。。。

#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const int MAXN = * 1e5 + , INF = 1e9 +;
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, num, mt, fa[MAXN];
struct Edge {
int u, v, w, f;
bool operator < (const Edge &rhs) const {return w > rhs.w;}
}E[MAXN];
void AddEdge(int x, int y, int z) {E[++num] = (Edge) {x, y, z};}
int comp(const Edge &a, const Edge &b) {return a.w < b.w;}
int find(int x) {return fa[x] == x ? fa[x] : (fa[x] = find(fa[x]));}
int calc() {
int ans = ;
for(int i = ; i <= num; i++) if(E[i].f) ans++;
return ans;
}
int Kruskal(int opt) {
if(opt == ) sort(E + , E + num + );
else sort(E + , E + num + , comp);
for(int i = ; i <= N; i++) fa[i] = i;
int cnt = ;
if(opt == )
for(int i = ; i <= num; i++)
if(E[i].f) fa[find(E[i].u)] = find(E[i].v), cnt++;
for(int i = ; i <= num; i++) {
int x = E[i].u, y = E[i].v, w = E[i].w;
int fx = find(x), fy = find(y);
if(fx == fy) continue;
if(opt == ) {
if(w == ) E[i].f = ;
if((++cnt) == N - ) return calc();
} else if(opt == ) {
cnt++; E[i].f = ;
if(cnt == K) return ;
} else if(opt == ) {
if(w == && (!E[i].f)) continue;
if((++cnt <= N - )) printf("%d %d %d\n", x, y, w);
}
fa[fx] = fy;
}
return ;
}
int main() {
N = read(); M = read(); K = read();
for(int i = ; i <= M; i++) {
int x = read(), y = read(), z = read();
AddEdge(x, y, z); //AddEdge(y, x, z);
}
if(Kruskal() > K) {puts("no solution"); return ;}
if(!Kruskal()) {puts("no soltion"); return ;}
Kruskal();
return ;
}

BZOJ3624: [Apio2008]免费道路(最小生成树)的更多相关文章

  1. [BZOJ3624][Apio2008]免费道路

    [BZOJ3624][Apio2008]免费道路 试题描述 输入 输出 输入示例 输出示例 数据规模及约定 见“输入”. 题解 第一步,先尽量加入 c = 1 的边,若未形成一个连通块,则得到必须加入 ...

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

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

  3. Kruskal算法及其类似原理的应用——【BZOJ 3654】tree&&【BZOJ 3624】[Apio2008]免费道路

    首先让我们来介绍Krukal算法,他是一种用来求解最小生成树问题的算法,首先把边按边权排序,然后贪心得从最小开始往大里取,只要那个边的两端点暂时还没有在一个联通块里,我们就把他相连,只要这个图里存在最 ...

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

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

  5. 题解 Luogu P3623 [APIO2008]免费道路

    [APIO2008]免费道路 题目描述 新亚(New Asia)王国有 N 个村庄,由 M 条道路连接.其中一些道路是鹅卵石路,而其它道路是水泥路.保持道路免费运行需要一大笔费用,并且看上去 王国不可 ...

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

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

  7. P3623 [APIO2008]免费道路

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

  8. [APIO2008]免费道路

    [APIO2008]免费道路 BZOJ luogu 先把必须连的鹅卵石路连上,大于k条no solution 什么样的鹅卵石路(u,v)必须连?所有水泥路都连上仍然不能使u,v连通的必须连 补全到k条 ...

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

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

随机推荐

  1. Flask05 cookie、类视图、方法视图、自己的404页面

    1 什么是cookie 就是网站存放到你浏览器中的一部分固定内容:当你下次访问我这个网站的时候,你会把之前我存放到你浏览器中的数据带回来给我        你要先登录(用户名.密码) ->   ...

  2. p1345 奶牛的电信Telecowmunication

    传送门 题目 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a ...

  3. git中避免提交.DS_Store文件[转载]

    1. 先删除原有的.DS_Store: find . -name .DS_Store -print0 | xargs -0 git rm -f --ignore-unmatch 命令解释:在当前文件夹 ...

  4. superset 错误解决

    访问superset localhost:8088   securety->list Role 报错 xxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxx ...

  5. Window 7 安装Docker toolbox , 启动terminal时遇到的小问题

    参考:http://blog.csdn.net/tina_ttl/article/details/51372604 参考前面网页成功安装后打开terminal,出现下面问题: Looks like s ...

  6. python sys.sdout.write 和print 区别

    sys.sdout.write 标准输入相当于“%value%”,输出内容没有空格,而print输出带有空格,举个例子 用sys.sdout.write: import sys for i in ra ...

  7. const define区别

    可以使用defined()----检测常量是否设置 [问]在php中定义常量时,const与define的区别? [答]使用const使得代码简单易读,const本身就是一个语言结构,而define是 ...

  8. CodeForces 137C【贪心+优先队列】

    这种区间的贪心好像都出"烂"了? 不过还是想写一下... 先按照区间左端点排序一下,然后搞个优先队列维护当前最小的右端点. #include <bits/stdc++.h&g ...

  9. 洛谷P1314 聪明的质监员

    P1314 聪明的质监员 题目描述 小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 n 个矿石,从 1到n 逐一编号,每个矿石都有自己的重量 wi 以及价值vi .检验矿产的流程是: ...

  10. 前端三部曲之Css-- 1(常见的居中方式)

    下面来介绍一下web端页面最常见的居中方式 页面的基本结构:一个简单的div <!DOCTYPE html> <html lang="en"> <he ...