題意:
主人公在一個類似於塔結構的地方..每一層有一個門..門上有兩個鑰匙孔..只要有其中的一片鑰匙就能開啟門繼續往上走了(一個門可能有兩個相同的鑰匙孔..也可能好幾個門都有相同的鑰匙孔..)..而所有的鑰匙被分成了N個pair..每個pair中只能拿一把鑰匙..現在問主人公最多能進入第幾層...
題解:
值得注意的是必須通過了K層才能進入K+1層...這樣就形成了一種單調關係...可以用二分來解決了..二分層數..然後2-sat判斷...
Program:
#include<iostream>#include<stdio.h>#include<string.h>#include<cmath>#include<queue>#include<stack>#include<set>#include<time.h>#include<map>#include<algorithm>#define ll long long#define eps 1e-5#define oo 10007#define pi acos(-1.0)#define MAXN 5005<<1#define MAXM 5000005<<1using namespace std; struct node{ int y,next;}line[MAXM];vector<int> T[MAXN];int Lnum,_next[MAXN],key[MAXN][2],hash[MAXN],door[MAXN][2];int dfn[MAXN],low[MAXN],tp[MAXN],tpnum,DfsIndex;bool instack[MAXN];stack<int> mystack;void addline(int x,int y){ line[++Lnum].next=_next[x],_next[x]=Lnum,line[Lnum].y=y;}void tarjan(int x){ instack[x]=true,mystack.push(x); dfn[x]=low[x]=++DfsIndex; for (int k=_next[x];k;k=line[k].next) { int y=line[k].y; if (!dfn[y]) { tarjan(y); low[x]=min(low[x],low[y]); }else if (instack[y]) low[x]=min(low[x],dfn[y]); } if (low[x]==dfn[x]) { tpnum++; do { x=mystack.top(); mystack.pop(); instack[x]=false; tp[x]=tpnum; }while (low[x]!=dfn[x]); }}bool _2sat(int N,int M){ int i,m,k; for (i=0;i<(N<<1);i++) T[i].clear(); for (i=1;i<=M;i++) T[door[i][0]].push_back(door[i][1]), T[door[i][1]].push_back(door[i][0]); Lnum=0,memset(_next,0,sizeof(_next)); for (i=0;i<N;i++) { int x=key[i][0],y=key[i][1]; m=T[y].size(); for (k=0;k<m;k++) addline(i<<1,hash[T[y][k]]); m=T[x].size(); for (k=0;k<m;k++) addline(i<<1|1,hash[T[x][k]]); } memset(dfn,0,sizeof(dfn)); memset(instack,false,sizeof(instack)); while (!mystack.empty()) mystack.pop(); DfsIndex=tpnum=0; for (i=0;i<(N<<1);i++) if (!dfn[i]) tarjan(i); for (i=0;i<N;i++) if (tp[i<<1]==tp[i<<1|1]) return false; return true;}int main(){ int N,M,i; while (~scanf("%d%d",&N,&M) && N) { for (i=0;i<N;i++) { scanf("%d%d",&key[i][0],&key[i][1]); hash[key[i][0]]=i<<1,hash[key[i][1]]=i<<1|1; } for (i=1;i<=M;i++) scanf("%d%d",&door[i][0],&door[i][1]); int l=0,r=M+1,mid; while (r-l>1) { mid=l+r>>1; if (!_2sat(N,mid)) r=mid; else l=mid; } printf("%d\n",l); } return 0;}