首页 > 代码库 > Ural1099 Work Scheduling 一般图的最大匹配

Ural1099 Work Scheduling 一般图的最大匹配

Ural1099

给定无向图, 求最大匹配。

在寻找增广路的过程中,可能出现一个奇环,这时候把奇环收缩,成为一朵“花”,并在新图上继续增广。

为了记录匹配关系,需要在花中寻找路径,每一条增广路径都可以通过把“花”展开还原回去(因为一个奇环上的两段路径必然一奇一偶)

给出代码,,理解不了就当模版吧 类似的算法还有朱刘算法

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=250,maxe=250*250*2;
bool g[maxn][maxn],inq[maxn],inflower[maxn];
int match[maxn],pre[maxn],color[maxn];
deque<int>Q;
int findlca(int u,int v)
{
 memset(inq,0,sizeof(inq));
 while(1)
 	{
 	 u=color[u];
 	 inq[u]=true;
 	 if(match[u]==-1)break;
 	 u=pre[match[u]];
	}
 while(1)
 	{
 	 v=color[v];
 	 if(inq[v])return v;
 	 v=pre[match[v]];
	}
}
void reset(int u,int lca)//以“花魁”为root重新设置路径 
{
 while(u!=lca)
 	{
 	 int v=match[u];
 	 inflower[color[u]]=inflower[color[v]]=true;
 	 v=pre[v];
 	 if(color[v]!=lca)pre[v]=match[u];
 	 u=v;
	}
}
void contract (int u,int v,int n)
{
 int lca=findlca(u,v);
 memset(inflower,0,sizeof(inflower));
 reset(u,lca);reset(v,lca);
 if(color[u]!=lca)pre[u]=v;
 if(color[v]!=lca)pre[v]=u;
 for(int i=1;i<=n;i++)
 	{
 	 if(inflower[color[i]])
 	 	{
 	 	 color[i]=lca;
 	 	 if(!inq[i])
 	 	 	{
 	 	 	 Q.push_back(i);
 	 	 	 inq[i]=1;
			}
		}
	}
}
bool dfs(int S,int n)
{
 for(int i=0;i<=n;i++)pre[i]=-1,inq[i]=0,color[i]=i;
 Q.clear();Q.push_back(S);inq[S]=1;
 while(!Q.empty())
 	{
 	 int u=Q.front();Q.pop_front();
	 for(int v=1;v<=n;v++)
	 	{
	 	 if(g[u][v]&&color[v]!=color[u]&&match[u]!=v)
	 	  {
	 	   if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))
	 	    contract(u,v,n);
	 	    else if(pre[v]==-1)
	 	    	{
	 	    	 pre[v]=u;
	 	    	 if(match[v]!=-1)Q.push_back(match[v]),inq[match[v]]=1;
	 	    	   else
	 	    	   		{
	 	    	   		 u=v;
	 	    	   		  while(u!=-1)
	 	    	   		  	{
	 	    	   		  	 v=pre[u];
	 	    	   		  	 int w=match[v];
	 	    	   		  	 match[u]=v;
	 	    	   		  	 match[v]=u;
	 	    	   		  	 u=w;
							}
						 return true;
						}	
				}
		  }
		}	
	}
 return false;
}
int main()
{
 int n,m,a,b,ans,i;
 while(scanf("%d",&n)!=EOF)
 	{
 	 ans=0;
 	 memset(match,-1,sizeof(match));
 	 memset(g,0,sizeof(g));
 	 while(scanf("%d%d",&a,&b)!=EOF&&a!=0)
 	 	{
 	 	 g[a][b]=g[b][a]=1;
		}
	 for(i=1;i<=n;i++)
	 	{
	 	 if(match[i]==-1&&dfs(i,n))
		  	{
		  	 ans++;
			}	
		}
	 cout<<ans*2<<endl;
	 for(i=1;i<=n;i++)
	 	if(match[i]!=-1)
	 		{
	 		 printf("%d %d\n",i,match[i]);
			 match[i]=match[match[i]]=-1;	
			}
	}
 return 0;
}

  

 

Ural1099 Work Scheduling 一般图的最大匹配