• 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
    ",i,match[i]);
    			 match[i]=match[match[i]]=-1;	
    			}
    	}
     return 0;
    }
    

      

  • 相关阅读:
    2021.02.09 【ABAP随笔】-Excel高效输出工具-xlsx workbench-输出多个Sheet
    2021.02.07 【ABAP随笔】-Excel高效输出工具-xlsx workbench
    Thrift did not exit cleanly
    Docker部署Springboot项目,Invalid or corrupt jarfile /app.jar
    为jenkins设置nginx作为反向代理
    Jenkins安装报错 No valid crumb was included in request
    判断当前设备是ios还是安卓
    vue 路由跳转四种方式 (带参数)
    Vue table的column属性,render函数生成switch开关和button按钮
    H5页面自定义 pxTorem 函数进行单位转换
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6753461.html
Copyright © 2020-2023  润新知