Poj 2723 Get Luffy Out (2-SAT + 二分)
2014-08-31 22:55
411 查看
参考了:POJ 2723 Get Luffy Out(2-SAT + 二分) - D_Double's Journey
题意:有2*N把不同的锁,每把锁有一个钥匙,共有2*N 把钥匙。把2*N把钥匙两两配对共分为N组。
有个M层楼,每层楼有一个门,每个门上有两把锁,可能是相同的也可能是不同的。 走上某层楼之前,必须要打开这个门上的至少一个锁。
从每组钥匙中只能选择一把钥匙,然后用这些钥匙去开门上楼,问最够能到几层?
思路:因为门只能按照顺序打开,所以用二分法将问题转化为判定问题。
对于一个门上的两把锁,如果这两把锁的钥匙是同一组的,那么任选一个钥匙就可以。
如果是属于不同组的,那么假设这两把钥匙是a1, b1,那么这两组分别是(a1, a2) (b1, b2), a2和b2是一定不能同时选的,因为选了就没有a1或b1来打开这个门了
所以<a2,b2>是一个矛盾对,加入边a1->b2, b2->a1
题意:有2*N把不同的锁,每把锁有一个钥匙,共有2*N 把钥匙。把2*N把钥匙两两配对共分为N组。
有个M层楼,每层楼有一个门,每个门上有两把锁,可能是相同的也可能是不同的。 走上某层楼之前,必须要打开这个门上的至少一个锁。
从每组钥匙中只能选择一把钥匙,然后用这些钥匙去开门上楼,问最够能到几层?
思路:因为门只能按照顺序打开,所以用二分法将问题转化为判定问题。
对于一个门上的两把锁,如果这两把锁的钥匙是同一组的,那么任选一个钥匙就可以。
如果是属于不同组的,那么假设这两把钥匙是a1, b1,那么这两组分别是(a1, a2) (b1, b2), a2和b2是一定不能同时选的,因为选了就没有a1或b1来打开这个门了
所以<a2,b2>是一个矛盾对,加入边a1->b2, b2->a1
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) const int MAXN = 2100; const int VN = MAXN*2; const int EN = VN; int n,m; struct Edge{ int v, next; }; class Graph{ public: int head[VN],size; Edge E[EN]; void init(){ size = 0; memset(head, -1, sizeof(head)); } void Add (int u,int v){ E[size].v = v; E[size].next = head[u]; head[u] = size++; } }g; class Two_Sat{ public: bool Check(const Graph&g, const int n){ SCC(g,n);//传入几对点 for (int i=0;i<n;i++) if (belong[i*2] == belong[i*2+1]) return false; return true; } private: int top, bcnt, idx; int sta[VN],belong[VN]; int dfn[VN],low[VN]; bool inStack[VN]; void targan (const Graph&g, const int u){ int v; dfn[u] = low[u] = ++idx; sta[top++] = u; inStack[u] = true; for (int i=g.head[u]; i!=-1; i=g.E[i].next){ v = g.E[i].v; if (dfn[v] < 0){ targan(g, v); low[u] = min(low[u], low[v]); } else if(inStack[v]) low[u] = min(low[u], dfn[v]); } if (dfn[u] == low[u]){ ++bcnt; do{ v = sta[--top]; inStack[v] = false; belong[v] = bcnt; }while(u != v); } } void SCC (const Graph&g, int n){ top=bcnt=idx=0; memset(dfn,-1,sizeof(dfn)); memset(low,0,sizeof(low)); memset(belong,0,sizeof(belong)); memset(inStack,false,sizeof(inStack)); for (int i=0; i<2*n;i++) if (dfn[i] < 0) targan(g,i); } }sat; int key[VN]; int door[MAXN][2]; int idx[VN]; int main () { int i; while (scanf("%d%d",&n,&m),n+m) { for (i=0;i<2*n;i++) { scanf("%d",&key[i]); idx[key[i]]=i; } for (i=0;i<m;i++) scanf("%d%d",&door[i][0],&door[i][1]); int low=0,high=m,mid; int ans=0; while (low<=high) { mid=(low+high)>>1; g.init(); for (i=0;i<mid;i++) { int a1=door[i][0], b1=door[i][1]; int a2=key[idx[a1]^1], b2=key[idx[b1]^1]; if (a2 == b1) continue; //同组钥匙 if (a1==b1) g.Add(idx[b1]^1, idx[b1]); //同一把钥匙 else g.Add(idx[a1], idx[b1]^1),g.Add(idx[b1], idx[a1]^1); } if (sat.Check(g,n)) ans = mid,low=mid+1; else high=mid-1; } printf("%d\n",ans); } return 0; }
相关文章推荐
- POJ2723_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
- [2-sat+二分]poj 2723 Get Luffy Out
- Get Luffy Out (poj 2723 二分+2-SAT)
- |poj 2723|2-SAT|二分|Get Luffy Out
- POJ 2723 Get Luffy Out 二分 + 2-sat
- Get Luffy Out (poj 2723 二分+2-SAT)
- POJ 2723 && HDU 1816 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 + 二分查找判断可行性】
- poj2723 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(图论-2SAT,搜索-二分)