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 ; }