題意:
和POJ2723差不多....唯一的區別在於前一題是把2N個要使分成了N對..而本題是組成了N對..說明可能有些鑰匙出現在多個pair中...
題解:
上一題是以每一pair取哪一個來構圖的...而本題就以每個鑰匙拿還是不拿來構圖....pair是有N個..而鑰匙是有2N個..範圍要留意...
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]; int Lnum,_next[MAXN],key[MAXN][2],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; Lnum=0,memset(_next,0,sizeof(_next)); for (i=1;i<=M;i++) { int x=door[i][0],y=door[i][1]; addline(x<<1,y<<1|1),addline(y<<1,x<<1|1); //對於一個門..必定是其中一把開啟 } for (i=0;i<N;i++) { int x=key[i][0],y=key[i][1]; addline(x<<1|1,y<<1),addline(y<<1|1,x<<1); //每對至多取一個鑰匙 } memset(dfn,0,sizeof(dfn)); memset(instack,false,sizeof(instack)); while (!mystack.empty()) mystack.pop(); DfsIndex=tpnum=0; for (i=0;i<(N<<2);i++) if (!dfn[i]) tarjan(i); for (i=0;i<(N<<1);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]); 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;}