链接
http://www.lydsy.com/JudgeOnline/problem.php?id=1191
题解
并查集。
把一道题目看做一条边,它能够使用的锦囊妙计看做两个点,这条边连接了这两个点。我们逐条边加入,容易发现,整张图中有很多连通块。如果一个连通块的边数等于点数-1,那么每条边肯定都能找到一个点和它匹配。
如果一个连通块的边数等于点数,说明这个块内有一个环,这时每条边依然能够找到一个和它匹配的点。
如果某次加入使得某个连通分量的边数大于点数,那么此时有一条边是无法找到和它匹配的点的,所以这条边不能被加入。
在第一条不能被加入的边处
break
,就得到答案了。
代码
//并查集
#include <cstdio>
#include <algorithm>
#define maxn 2000
using namespace std;
int f[maxn], edge[maxn], N, M;
int find(int x)
{
if(x==f[x])return x;
f[x]=find(f[x]);
edge[f[x]]+=edge[x];
edge[x]=0;
return f[x];
}
void merge(int x, int y){f[find(x)]=find(y);}
int getsz(int x)
{
int i, cnt=0;
for(i=1;i<=N;i++)if(find(i)==x)cnt++;
return cnt;
}
int main()
{
int i, x, y, j;
scanf("%d%d",&N,&M);
for(i=1;i<=N;i++)f[i]=i;
for(i=1;i<=M;i++)
{
scanf("%d%d",&x,&y);x++,y++;
merge(x,y);edge[x]++;
for(j=1;j<=N;j++)find(j);
if(edge[f[x]]>getsz(f[x]))break;
}
printf("%d",i-1);
return 0;
}