题意:给你一些钥匙,按顺序有m个门,问最多可以打开多少个门。钥匙是成对的,只能使用一对中的一个钥匙。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
const int N = 1029;
const int M = 2049;
int n,m;
int hash[N<<2];
struct LT{
int to,nex;
} L[M<<2];
int F[N<<2],cnt;
void add(int f,int t)
{
L[cnt].nex =F[f];
L[cnt].to = t;
F[f] = cnt++;
}
struct ff{
int l,r;
} re[M];
void init()
{
int f,t;
for(int i=0;i<n;i++)
{
scanf("%d%d",&f,&t);
hash[f] = t;hash[t] = f;
}
for(int i=0;i<m;i++)
scanf("%d%d",&re[i].l,&re[i].r);
}
int dfn[N<<2],low[N<<2],col[N<<2],ind,color;
bool post[N<<2];
stack<int> S;
void tdfs(int k){
dfn[k] = low[k] =ind++;
post[k] = true;
S.push(k);
for(int i=F[k];i;i=L[i].nex){
int to = L[i].to;
if(!dfn[to]){
tdfs(to);
low[k] = min(low[k],low[to]);
}else if(post[to]&&low[k]>dfn[to]){
low[k] = dfn[to];
}
}
if(dfn[k]==low[k]){
color++;int i;
for(i=S.top(),S.pop();i!=k;i=S.top(),S.pop())
{
col[i] = color; post[i] = false;
}
col[i]=color,post[i] = false;
}
}
bool tarjan()
{
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(col,0,sizeof(col));
ind=1;color=0;
for(int i=0;i<(n<<2);i++)
if(!dfn[i]) tdfs(i);
for(int i=0;i<(n<<1);i++)
if(col[i]==col[i+n*2]) return false;
return true;
}
void solve()
{
int ans,l=0,r=m,mid;
while(l<=r)
{
mid = (l+r)>>1;
memset(F,0,sizeof(F));cnt = 1;
for(int i=0;i<(n<<1);i++)
add(i,hash[i]+2*n);
for(int i=0;i<mid;i++)
if(re[i].l!=re[i].r)
add(re[i].r+n*2,re[i].l),add(re[i].l+n*2,re[i].r);
else
add(re[i].l+n*2,re[i].r);
if(tarjan())
ans = mid,l=mid+1;
else
r=mid-1;
}
printf("%d\n",ans);
}
int main()
{
freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m)&&(n+m))
{
init();
solve();
}
return 0;
}