一般图最大匹配带花树+暴力:
先算最大匹配 C1
在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2
如果C2+2==C1则这条边再某个最大匹配中
4 4 1 3 2 3 2 4 3 1 6 6 1 2 3 2 3 4 5 2 5 4 5 6
1 2 3 2 4 5
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <vector> using namespace std; const int maxn=50; vector<int> ans; bool G[maxn][maxn],TG[maxn][maxn]; int n,m; int Match[maxn]; int Start,Finish,NewBase; int Father[maxn],Base[maxn]; bool InQueue[maxn],InPath[maxn],InBlossom[maxn]; int Count; queue<int> q; int FindCommonAncestor(int u,int v) { memset(InPath,false,sizeof(InPath)); while(true) { u=Base[u]; InPath[u]=true; if(u==Start) break; u=Father[Match[u]]; } while(true) { v=Base[v]; if(InPath[v]) break; v=Father[Match[v]]; } return v; } void ResetTrace(int u) { int v; while(Base[u]!=NewBase) { v=Match[u]; InBlossom[Base[u]]=InBlossom[Base[v]]=true; u=Father[v]; if(Base[u]!=NewBase) Father[u]=v; } } void BlossomContract(int u,int v) { NewBase=FindCommonAncestor(u,v); memset(InBlossom,false,sizeof(InBlossom)); ResetTrace(u); ResetTrace(v); if(Base[u]!=NewBase) Father[u]=v; if(Base[v]!=NewBase) Father[v]=u; for(int tu=1;tu<=n;tu++) { if(InBlossom[Base[tu]]) { Base[tu]=NewBase; if(!InQueue[tu]) { q.push(tu); InQueue[tu]=true; } } } } void FindAugmentingPath() { memset(InQueue,false,sizeof(InQueue)); memset(Father,0,sizeof(Father)); for(int i=1;i<=n;i++) Base[i]=i; while(!q.empty()) q.pop(); q.push(Start); InQueue[Start]=true; Finish=0; while(!q.empty()) { int u=q.front(); q.pop(); InQueue[u]=false; for(int i=1;i<=n;i++) { if(i==u||G[u][i]==false) continue; int v=i; if(Base[u]!=Base[v]&&Match[u]!=v) { if(v==Start||(Match[v]>0&&Father[Match[v]]>0)) BlossomContract(u,v); else if(Father[v]==0) { Father[v]=u; if(Match[v]>0) { q.push(Match[v]); InQueue[Match[v]]=true; } else { Finish=v; return ; } } } } } } void AugmentPath() { int u,v,w; u=Finish; while(u>0) { v=Father[u]; w=Match[v]; Match[v]=u; Match[u]=v; u=w; } } void Edmonds() { memset(Match,0,sizeof(Match)); for(int u=1;u<=n;u++) { if(Match[u]==0) { Start=u; FindAugmentingPath(); if(Finish>0) AugmentPath(); } } } int bian[200][2]; int main() { while(scanf("%d%d",&n,&m)!=EOF) { memset(G,0,sizeof(G)); memset(TG,0,sizeof(TG)); ans.clear(); for(int i=0;i<m;i++) { int u,v; scanf("%d%d",&u,&v); bian[i][0]=u;bian[i][1]=v; G[u][v]=G[v][u]=1; TG[u][v]=TG[v][u]=1; } Edmonds(); Count=0; for(int i=1;i<=n;i++) if(Match[i]) Count++; for(int i=0;i<m;i++) { int u=bian[i][0],v=bian[i][1]; ///clear about u,v for(int j=1;j<=n;j++) { G[u][j]=G[j][u]=G[j][v]=G[v][j]=0; } Edmonds(); int C2=0; for(int j=1;j<=n;j++) if(Match[j]) C2++; if(C2<Count-2) ans.push_back(i+1); ///Recover for(int j=1;j<=n;j++) { G[u][j]=TG[u][j]; G[j][u]=TG[j][u]; G[v][j]=TG[v][j]; G[j][v]=TG[j][v]; } } int sz = ans.size(); printf("%d\n",sz); for(int i=0;i<sz;i++) { printf("%d",ans[i]); if(i<sz-1)printf(" "); } printf("\n"); } return 0; }