http://acm.fzu.edu.cn/problem.php?pid=1202
二分图最大匹配,问哪些边是必要的,O(n^3)的方法
删边的时候把连接关系也要删掉,如果在此基础上无法找到增广路,加入答案,恢复连接关系,如果能找到,连接关系不用恢复(因为要n对匹配,这组匹配新的了剩下的要留给别的组)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
int T,M[105][105],n,linkx[105],linky[105],vis[105],a[105],b[105] ;
int find(int s)
{
for(int i=1 ;i<=n ;i++)
{
if(M[s][i])
{
if(vis[i]==T)continue ;
vis[i]=T ;
if(!linky[i] || find(linky[i]))
{
linky[i]=s ;
linkx[s]=i ;
return 1 ;
}
}
}
return 0 ;
}
int max_match()
{
int ans=0 ;
memset(linkx,0,sizeof(linkx)) ;
memset(linky,0,sizeof(linky)) ;
memset(vis,0,sizeof(vis)) ;
for(int i=1 ;i<=n ;i++)
{
T=i ;
ans+=find(i);
}
return ans;
}
struct node
{
int first,second ;
}ans[105] ;
int cmp(node aa,node bb)
{
if(aa.first==bb.first)return aa.second<bb.second ;
return aa.first<bb.first ;
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=0 ;i<105 ;i++)
for(int j=0 ;j<105 ;j++)
M[i][j]=1 ;
while(1)
{
int xx,yy ;
scanf("%d%d",&xx,&yy) ;
if(!xx && !yy)break ;
M[xx][yy]=0 ;
}
int res=max_match() ;
if(res!=n)
{
puts("none") ;
putchar(‘\n‘) ;
continue ;
}
int st=0 ;
memset(vis,0,sizeof(vis)) ;
for(int i=1 ;i<=n ;i++)
{
T=i ;
int temp=linkx[i] ;
M[i][temp]=0 ;
linkx[i]=0 ;linky[temp]=0 ;
if(!find(i))
{
ans[st].first=i ;
ans[st++].second=temp ;
linkx[i]=temp ;
linky[temp]=i ;
}
M[i][temp]=1 ;
}
if(st)
{
sort(ans,ans+st,cmp) ;
for(int i=0 ;i<st ;i++)
printf("%d %d\n",ans[i].first,ans[i].second) ;
}
else puts("none") ;
putchar(‘\n‘) ;
}
return 0 ;
}
时间: 2024-08-10 21:14:30