首先是要构造二分图,然后二分图的最大匹配。
还有没完全证明过我的方法的正确性,但是AC了.....
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; const int INF=0x7FFFFFFF; const int maxn=200*200+10; const int Maxn=200+10; int N,M; int U[maxn],V[maxn]; int F[Maxn]; vector<int>G[Maxn]; int St; int dis[Maxn],flag[Maxn]; queue<int>Q; int Belong[Maxn]; int nx,ny; int g[Maxn][Maxn]; int cx[Maxn],cy[Maxn]; int mk[Maxn]; void init() { for(int i=0; i<=N; i++) G[i].clear(); memset(F,0,sizeof F); memset(Belong,0,sizeof Belong); for(int i=0; i<=N; i++) dis[i]=INF; nx=N,ny=N; memset(g,0,sizeof(g)); } void SPFA() { while(!Q.empty()) Q.pop(); memset(flag,0,sizeof flag); flag[St]=1; dis[St]=0; Q.push(St); while(!Q.empty()) { int h=Q.front(); Q.pop(); flag[h]=0; for(int i=0; i<G[h].size(); i++) { if(dis[h]+1<dis[G[h][i]]) { dis[G[h][i]]=dis[h]+1; if(!flag[G[h][i]]) { flag[G[h][i]]=1; Q.push(G[h][i]); } } } } } int path(int u) { for(int v=1; v<=ny; v++) { if(g[u][v]&&!mk[v]) { mk[v]=1; if(cy[v]==-1||path(cy[v])) { cx[u]=v; cy[v]=u; return 1; } } } return 0; } int MaxMatch() { int res=0; memset(cx,-1,sizeof(cx)); memset(cy,-1,sizeof(cy)); for(int i=1; i<=nx; i++) { if(cx[i]==-1) { memset(mk,0,sizeof(mk)); res=res+path(i); } } return res; } int main() { while(~scanf("%d%d",&N,&M)) { init(); for(int i=1; i<=M; i++) scanf("%d%d",&U[i],&V[i]); for(int i=1; i<=M; i++) { G[U[i]].push_back(V[i]); G[V[i]].push_back(U[i]); } for(int i=1; i<=N; i++) if(dis[i]==INF) St=i,SPFA(); for(int i=1; i<=N; i++) { if(dis[i]%2==0) Belong[i]=2; else Belong[i]=1; } int Fail=0; for(int i=1; i<=M; i++) if(Belong[U[i]]==Belong[V[i]]) { Fail=1; break; } if(Fail==1) printf("No "); else { for(int i=1; i<=M; i++) { if(Belong[U[i]]==1&&Belong[V[i]]==2) g[U[i]][V[i]]=1; if(Belong[V[i]]==1&&Belong[U[i]]==2) g[V[i]][U[i]]=1; } printf("%d ",MaxMatch()); } } return 0; }