【NOIP2010】关押罪犯 (二分+图染色)||(贪心+并查集)
来源:互联网 发布:淘宝店能上传多少宝贝 编辑:程序博客网 时间:2024/06/05 04:50
Freda 的试题分析:
解法一:二分答案+染色
二分答案,对于答案 P。建立对应的图,将冲突值大于 P 的两个罪犯对应的点连边。然后将点染成 1/2两种颜色,有边相连的两点不能同色。半段是否可行(有删减)。
解法二:贪心+并查集
按边权从大到小排序。依次处理每条边,如果这条边连接的点还没有被并入一个集合,那么将其并入一个集合,并且设二者不再一个监狱里。否则,如果二者在一个集合且产生矛盾,终止算法得到答案。
(补充:因为我们无法知道某2个点到底应该放在哪个集合里, 我们开一个两倍大小的并查集,加边时,分别加边。来自hzwer)
解法一代码:
#include <cstdio>#include <cstring>#include <iostream>#include <cstdlib>#include <algorithm>using namespace std;#define MAXN (20020)#define MAXM (101000)int n, m, tot = 0;int first[MAXN], nxt[MAXM << 1];int vis[MAXN];struct edge{ int from, to, cost;}sour[MAXM], es[MAXM << 1];void build(int ff, int tt, int dd){ es[++tot] = (edge){ff,tt,dd}; nxt[tot] = first[ff]; first[ff] = tot;}bool dfs(int x, int c){ vis[x] = c; for(int i = first[x]; i != -1; i = nxt[i]) { int v = es[i].to; if(vis[v]) { if(vis[v] == vis[x]) return 0; continue; } if(!dfs(v, c==1?2:1)) return 0; } return 1;}bool check(int mid){ tot = 0; memset(first,-1,sizeof(first)); memset(nxt,0,sizeof(nxt)); memset(vis,0,sizeof(vis)); memset(es,0,sizeof(es)); for(int i = 1; i <= m; ++ i) { if(sour[i].cost > mid) { build(sour[i].from,sour[i].to,sour[i].cost); build(sour[i].to,sour[i].from,sour[i].cost); } } for(int i = 1; i <= n; ++ i) if(!vis[i]) if(!dfs(i,1)) return false; return true;}bool cmp(edge a, edge b){ return a.cost < b.cost;}int main(){ cin >> n >> m; for(int i = 1; i <= m; ++ i) scanf("%d%d%d", &sour[i].from, &sour[i].to, &sour[i].cost); if(n <= 2) { puts("0"); return 0; } sort(sour+1,sour+m+1,cmp); int l = 0, r = m, ans = 1e9, mid; while(r-l > 1) { mid = (l+r)>>1; if(check(sour[mid].cost)) r = mid, ans = min(ans, sour[mid].cost); else l = mid; } cout << ans << endl; return 0;}
解法二代码:
#include <cstdio>#include <cstring>#include <iostream>#include <cstdlib>#include <algorithm>using namespace std;#define MAXN (20020)#define MAXM (101000)int n, m, tot = 0;int fa[MAXN*2];struct edge{ int from, to, cost;}sour[MAXM];bool cmp(edge a, edge b){ return a.cost > b.cost;}int find(int x){ int r = x; while(r != fa[r]) r = fa[r]; int t; while(x != r) { t = fa[x]; fa[x] = r; x = t; } return r;}int main(){ cin >> n >> m; for(int i = 1; i <= m; ++ i) scanf("%d%d%d", &sour[i].from, &sour[i].to, &sour[i].cost); sort(sour+1,sour+m+1,cmp); for(int i = 1; i <= n*2; ++ i) fa[i] = i; for(int i = 1; i <= m; ++ i) { int f = sour[i].from, t = sour[i].to, c = sour[i].cost; int fx = find(f), fy = find(t); if(fx == fy) {cout << c << '\n'; return 0;} fa[fx] = find(t+n); fa[fy] = find(f+n); } puts("0"); return 0;}
2 0
- 【NOIP2010】关押罪犯 (二分+图染色)||(贪心+并查集)
- 【noip2010】codevs 1069 关押罪犯(二分+BFS染色||并查集)
- noip2010 关押罪犯 (并查集处理二分图分配)
- 关押罪犯-详解-noip2010-并查集--搜索--二分图
- [NOIP2010]关押罪犯(二分+二分图染色)
- NOIP2010提高组 关押罪犯(并查集)
- 关押罪犯 codevs 1069(整理:加权并查集?+虚点并查集+二分图染色)
- 【noip2010提高组】 关押罪犯 并查集+贪心
- [NOIP2010][并查集][二分答案]关押罪犯
- 【洛谷 1525】关押罪犯 并查集||二分+染色
- 【并查集】【Noip2010】关押罪犯
- 【NOIP2010】关押罪犯 虚点并查集
- NOIP2010 Codevs 1069 关押罪犯 [并查集] [二分图判定]
- NOIP2010 关押罪犯 (二分答案+二分图染色)
- codevs 1069 [NOIP2010] 关押罪犯 二分+二分图染色
- NOIP 2010 关押罪犯 并查集 二分+二分图染色
- 【图-二分图染色】NOIP2010提高组关押罪犯
- wikioi1069关押罪犯(贪心+并查集 kruskal算法)
- UML学习(一)-----用例图
- Python开发实用小技巧
- Zookeeper Watch监听
- Udacity DEEPLEARNING 学习笔记 L3 CONVOLUTIONAL NEURAL NETWORKS
- apk文件构建过程图解
- 【NOIP2010】关押罪犯 (二分+图染色)||(贪心+并查集)
- 求取最大公约数的算法分析
- 【codevs1453 统计素数个数2】E氏筛法
- hdu 1029(模拟)
- tomcat设置IP地址或者域名访问
- 正则表达式匹配中文
- MFC+DuiVision结合VLC播放器开发直播客户端
- makefile基本介绍
- sdut 懒虫小鑫