POJ 2723 HDU 1816 Get Luffy Out
二分答案 + 2-SAT验证
#include<cstdio> #include<cstring> #include<cmath> #include<stack> #include<queue> #include<algorithm> using namespace std; const int maxn=60000+10; int N,M; stack<int>S; vector<int>G[maxn]; vector<int>FG[maxn]; int Belong[maxn]; int flag[maxn]; int Block; int doorX[maxn],doorY[maxn]; int keyX[maxn],keyY[maxn]; int left,right,mid,ans; void init() { for(int i=0; i<maxn; i++) G[i].clear(); for(int i=0; i<maxn; i++) FG[i].clear(); memset(Belong,0,sizeof Belong); memset(flag,0,sizeof flag); while(!S.empty()) S.pop(); Block=0; } void addEdge(int x,int y) { G[x].push_back(y); FG[y].push_back(x); } void dfs1(int now) { flag[now]=1; for(int i=0; i<G[now].size(); i++) if(!flag[G[now][i]]) dfs1(G[now][i]); S.push(now); } void dfs2(int now) { Belong[now]=Block; for(int i=0; i<FG[now].size(); i++) if(!Belong[FG[now][i]]) dfs2(FG[now][i]); } bool judge() { for(int i=0; i<2*2*N; i++) if(!flag[i]) dfs1(i); while(!S.empty()) { int Top=S.top(); S.pop(); if(!Belong[Top]) { Block++; dfs2(Top); } } for(int i=0; i<2*N; i++) if(Belong[2*i]==Belong[2*i+1]) return 0; return 1; } void read() { for(int i=0;i<N;i++) scanf("%d%d",&keyX[i],&keyY[i]); for(int i=0;i<M;i++) scanf("%d%d",&doorX[i],&doorY[i]); } int main() { while(~scanf("%d%d",&N,&M)) { if(!N&&!M) break; read(); left=0,right=M; while(left<=right) { mid=(left+right)/2; init(); for(int i=0;i<N;i++) { addEdge(2*keyX[i]+1,2*keyY[i]); addEdge(2*keyY[i]+1,2*keyX[i]); } for(int i=0;i<mid;i++) { addEdge(2*doorX[i],2*doorY[i]+1); addEdge(2*doorY[i],2*doorX[i]+1); } if(judge()){ans=mid;left=mid+1;} else right=mid-1; } printf("%d\n",ans); } return 0; }