POJ 2723 Get Luffy Out (2-sat)
来源:互联网 发布:帝国cms 灵动标签 编辑:程序博客网 时间:2024/04/19 16:03
这道题刚开始读错了题目,以为是每层有两个门,后来再仔细看,还好,是一个门,那么就是比较简单的也是比较典型的2-sat了!
首先,先总结一下2-sat的解题思路:根据我做的比较有限的题目,就是感觉一定要去找条件,找矛盾!有的题目是要求最优解,所以要结合条件来建图,然后用2-sat判定可行性,用二分来找最优解!有的题目比较简单就是直接判断是否解。此外,还有要输出最优解的情况,这个我还没有做到输出方案的题目,据说是要缩点,形成一个SCC图。
接下来,说一下这道题:
第一,每个对钥匙之间是有关系的
第二,每个门上的两个锁至少要开一个才能把这个门打开
因此建图,(要注意建图方向,2-sat的边都是必要边,就是一个条件成立了,那么另一个必须成立,所以一定要注意边的方向),对于每对钥匙,必须是互斥的关系,a->!b, b->!a;对于每个门上的对应的钥匙,如果要开门,一定是 !a->b, !b->a;同时,这个门的出现是顺序的,而且要知道,限定的关系越多,不成立的可能性越大,到底是限定到第几个门的时候才是最大的可以开始的门数量呢,这个问题解决的办法就是二分查找!查找最多能开到第几个门!二分这个方法很常见,如果当前的mid成立,那么就试探再大一些的,如果当前的不成立,就试探小一些的,最后求出了的就是最优解!
代码:
#include <cstdio>#include <cstring>#include <iostream>#include <stack>#include <vector>#include <algorithm>using namespace std;const int N = 6000;vector< int > G[N];int n, m;int lowlink[N], pre[N], sccno[N], scc_cnt, dfs_clock;int a[N], b[N], nx[N], ny[N];stack <int> S;void init(){ for ( int i = 0; i <= n*4; ++i ) G[i].clear();}void build ( int mid ){ for ( int i = 0; i < n; ++i ) { G[a[i]*2+1].push_back(b[i]*2); G[b[i]*2+1].push_back(a[i]*2); } for ( int i = 0; i < mid; ++i ) { G[nx[i]*2].push_back(ny[i]*2+1); G[ny[i]*2].push_back(nx[i]*2+1); }}void Tarjan(int u){ pre[u] = lowlink[u] = ++dfs_clock; S.push(u); for ( int i = 0; i < G[u].size(); ++i ) { int v = G[u][i]; if ( !pre[v] ) { Tarjan(v); lowlink[u] = min( lowlink[v], lowlink[u] ); } else if ( !sccno[v] ) lowlink[u] = min( lowlink[u], pre[v] ); } if ( lowlink[u] == pre[u] ) { scc_cnt++; for(;;) { int x = S.top(); S.pop(); sccno[x] = scc_cnt; if ( x == u ) break; } }}void find_scc( int nodenum ) { dfs_clock = scc_cnt = 0; memset(sccno, 0, sizeof(sccno)); memset(pre, 0, sizeof(pre)); for ( int i = 0; i < nodenum; ++i ) if ( !pre[i] ) Tarjan(i);}bool solve(int nodenum){ for ( int i = 0; i < nodenum; i++ ) if ( sccno[i*2] == sccno[i*2+1] ) return false; return true;}int main(){ while ( scanf("%d%d", &n, &m) == 2 && n+m ) { for ( int i = 0; i < n; ++i ) { scanf("%d%d", &a[i], &b[i]); } for ( int i = 0; i < m; ++i ) { scanf("%d%d", &nx[i], &ny[i]); } int l = 0, r = m, mid, ans; while ( l <= r ) { mid = (l+r) / 2; init(); build(mid); find_scc(n*4); if ( solve(n*2) ) { ans = mid; l = mid+1; } else r = mid-1; } printf("%d\n", ans); }}
- POJ 2723 Get Luffy Out(2-SAT)
- poj 2723 Get Luffy Out 2sat
- 2-sat->poj 2723 Get Luffy Out
- POJ 2723 Get Luffy Out(2-SAT)
- poj 2723 Get Luffy Out 2-SAT
- poj 2723 Get Luffy Out 2-sat
- POJ 2723 - Get Luffy Out(2-SAT)
- poj 2723 Get Luffy Out 2-SAT
- POJ 2723 Get Luffy Out(2-SAT)
- poj 2723 Get Luffy Out 2-SAT
- POJ 2723 Get Luffy Out (2-sat)
- poj 2723 Get Luffy Out(2-sat + 二分)
- poj 2723 Get Luffy Out(图论-2-sat)
- Get Luffy Out (poj 2723 二分+2-SAT)
- POJ 2723Get Luffy Out (2-SAT)
- 【HDU】1816 Get Luffy Out * &【POJ】2723 Get Luffy Out 【2-sat】
- POJ--2723[Get Luffy Out] 第二道2—SAT
- [2-sat+二分]poj 2723 Get Luffy Out
- HDU2036:改革春风吹满地
- 读 《JavaScript: The Good Parts》 有感
- Divideing Jewels
- (最小生成树-Prim)PKU-1258 Agri-Net
- TextFlow 文本可视化
- POJ 2723 Get Luffy Out (2-sat)
- 数据库死锁问题和事务
- 解决ubuntu12.04下gedit乱码问题
- 多态
- 洗牌、发牌算法 (打乱扑克牌顺序)
- 再谈osg场景中的树(3dmax建模)
- nodejs 向mongodB获取指定数目的数据
- java char c = '中'是否正确
- Percona Server for MySQL 5.5.30