BZOJ 3624 [Apio2008]免费道路:并查集 + 生成树 + 贪心【恰有k条特殊路径】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3624
题意:
给你一个无向图,n个点,m条边。
有两种边,种类分别用0和1表示。
让你求一棵生成树,使得这棵树中恰好有k条0种类的边。输出每一条边的两端点和种类。
若无解,则输出"no solution"。
题解:
让0和1分别作两种边的边权。
步骤:
(1)先找出必须选的0边。(优先选1,最大生成树)
(2)再将0边个数加至k。
(3)补上1边。
AC Code:
- #include <iostream>
- #include <stdio.h>
- #include <string.h>
- #include <algorithm>
- #include <vector>
- #define MAX_N 20005
- using namespace std;
- struct Edge
- {
- int sour;
- int dest;
- int len;
- Edge(int _sour,int _dest,int _len)
- {
- sour=_sour;
- dest=_dest;
- len=_len;
- }
- Edge(){}
- friend bool operator < (const Edge &a,const Edge &b)
- {
- return a.len<b.len;
- }
- };
- int n,m,k;
- int par[MAX_N];
- bool failed=false;
- vector<Edge> edge;
- vector<Edge> est;
- vector<Edge> ans;
- void read()
- {
- cin>>n>>m>>k;
- int a,b,c;
- for(int i=;i<m;i++)
- {
- cin>>a>>b>>c;
- edge.push_back(Edge(a,b,c));
- }
- }
- void init_union_find()
- {
- for(int i=;i<=n;i++)
- {
- par[i]=i;
- }
- }
- int find(int x)
- {
- return par[x]==x?x:par[x]=find(par[x]);
- }
- void unite(int x,int y)
- {
- int px=find(x);
- int py=find(y);
- if(px==py) return;
- par[px]=py;
- }
- bool same(int x,int y)
- {
- return find(x)==find(y);
- }
- void max_tree()
- {
- init_union_find();
- sort(edge.begin(),edge.end());
- int cnt=;
- for(int i=edge.size()-;i>=;i--)
- {
- Edge temp=edge[i];
- if(!same(temp.sour,temp.dest))
- {
- cnt++;
- unite(temp.sour,temp.dest);
- if(temp.len==) est.push_back(temp);
- }
- }
- if(cnt!=n- || est.size()>k) failed=true;
- }
- void min_tree()
- {
- init_union_find();
- int cnt=;
- int spe=;
- for(int i=;i<est.size() && spe<k;i++)
- {
- Edge temp=est[i];
- cnt++;
- spe++;
- ans.push_back(temp);
- unite(temp.sour,temp.dest);
- }
- for(int i=;i<edge.size();i++)
- {
- Edge temp=edge[i];
- if(!same(temp.sour,temp.dest))
- {
- if(temp.len==)
- {
- if(spe<k)
- {
- cnt++;
- spe++;
- ans.push_back(temp);
- unite(temp.sour,temp.dest);
- }
- }
- else
- {
- cnt++;
- ans.push_back(temp);
- unite(temp.sour,temp.dest);
- }
- }
- }
- if(cnt!=n- || spe!=k) failed=true;
- }
- void solve()
- {
- max_tree();
- min_tree();
- }
- void print()
- {
- if(failed)
- {
- cout<<"no solution"<<endl;
- return;
- }
- for(int i=;i<ans.size();i++)
- {
- Edge temp=ans[i];
- cout<<temp.sour<<" "<<temp.dest<<" "<<temp.len<<endl;
- }
- }
- int main()
- {
- read();
- solve();
- print();
- }
BZOJ 3624 [Apio2008]免费道路:并查集 + 生成树 + 贪心【恰有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: ...
- 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 这 ...
- BZOJ 3624: [Apio2008]免费道路 [生成树 并查集]
题意: 一张图0,1两种边,构造一个恰有k条0边的生成树 优先选择1边构造生成树,看看0边是否小于k 然后保留这些0边,补齐k条,再加1边一定能构成生成树 类似kruskal的证明 #include ...
- BZOJ.3624.[APIO2008]免费道路(Kruskal)
题目链接 我们发现有些白边是必须加的,有些是多余的. 那么我们先把所有黑边加进去,然后把必须要加的白边找出来. 然后Kruskal,把必须要加的白边先加进去,小于K的话再加能加的白边.然后加黑边. 要 ...
- 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 ...
随机推荐
- TextView划线 android
TextView 加下划线 . 中划线 下过如图: // 中划线 textView.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.A ...
- vue.js+koa2项目实战(三)登录注册模态框
登录注册模态框 注: [Vue warn]: Do not use built-in or reserved HTML elements as component id: diaLog 原因:diaL ...
- PyInstaller把.py转为.exe
http://www.pyinstaller.org/ http://blog.csdn.net/hmy1106/article/details/45151409 python pyinstaller ...
- Java String 常用函数
1>获取 1.1:字符串中包含的字符数,也就是字符串的长度. int length():获取长度 1.2:根据位置获取位置上某个字符. char charAt(int index) ...
- UbuntuServer12.04安装MongoDB,开机自启,服务,权限
获取最新版本 去http://www.mongodb.org/downloads找最新版的链接 wget http://fastdl.mongodb.org/linux/mongodb-linux-x ...
- leetCode 84.Largest Rectangle in Histogram (最大矩形直方图) 解题思路和方法
Given n non-negative integers representing the histogram's bar height where the width of each bar is ...
- mysql 相关博客地址
MySQL概念学习与逐步上手操作系列(一套完整) https://www.cnblogs.com/zlslch/category/962962.html
- os如何处理键盘的所有按键,显示or不显示,显示是如何显示
[0]README 0.1) source code and text decription are from orange's implemention of a os , and for comp ...
- HttpClient 访问 https 出现peer can't
package util; import java.security.cert.CertificateException; import javax.net.ssl.SSLContext;import ...
- springmvc的过滤器和拦截器
1 什么是过滤器 过滤器是过滤数据,比如过滤低俗文字,修改字符编码等. 2 什么是拦截器 拦截器中可以用来向ModelAndView中添加通用的数据.这样的好处是对于所有网页的公用部分就不需要在每个c ...