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

  

时间: 2024-08-06 00:58:48

Ural1099 Work Scheduling 一般图的最大匹配的相关文章

URAL 1099 Work scheduling 一般图的最大匹配 带花树算法(模板)

R - Work scheduling Time Limit:500MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice URAL 1099 Description There is certain amount of night guards that are available to protect the local junkyard from possible junk r

POJ 2226 缩点建图+二分图最大匹配

这个最小覆盖但不同于 POJ 3041,只有横或者竖方向连通的点能用一块板子覆盖,非连续的,就要用多块 所以用类似并查集方法,分别横向与竖向缩点,有交集的地方就连通,再走一遍最大匹配即可 一开始还有点没想清楚缩点怎么写,其实就是横向和竖向分别缩一下,不要混在一起,否则很麻烦,要注意一下 #include <iostream> #include <cstdio> #include <cstring> using namespace std; char mat[900][9

求无权图的最大匹配---匈牙利算法

匈牙利算法 匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名,,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法. [先介绍几个概念] 匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点.例如,图3.图4 中红色的边就是图 2 的匹配. 我们定义匹配点.匹配边.未匹配点.非匹配边,它们的含义非常显然.例如图 3中 1.4.5.7为匹配点,其他顶点为未匹配点:1-5.4-7为匹配边,其他边为

URAL 1099. Work Scheduling 一般图匹配带花树

一般图匹配带花树模版题: 将奇环缩成圈(Blossom),然后找增广路..... 1099. Work Scheduling Time limit: 0.5 second Memory limit: 64 MB There is certain amount of night guards that are available to protect the local junkyard from possible junk robberies. These guards need to sche

一般图的最大匹配(模板)

题:http://uoj.ac/problem/79 没什么好说的,只是区别于二分图 算法:带花树算法 #include<bits/stdc++.h> using namespace std; #define fo(i,a,b) for(int i=a;i<=b;i++) #define fod(i,a,b) for(int i=b;i>=a;i--) const int N=550; int n,head[N],pre[N],match[N],f[N],col[N],cmp[N]

&quot;《算法导论》之‘图’&quot;:不带权二分图最大匹配(匈牙利算法)

博文“二分图的最大匹配.完美匹配和匈牙利算法”对二分图相关的几个概念讲的特别形象,特别容易理解.本文介绍部分主要摘自此博文. 还有其他可参考博文: 趣写算法系列之--匈牙利算法 用于二分图匹配的匈牙利算法 1. 前言 二分图:简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图.准确地说:把一个图的顶点划分为两个不相交集 U 和V ,使得每一条边都分别连接U.V中的顶点.如果存在这样的划分,则此图为一个二分图.二分图的一个等价定义是:不含有「含奇数条边的环」的图.

带花树——一般图最大匹配

问题 给定一个图,求该图的最大匹配.即找到最多的边,使得每个点至多属于一条边. 这个问题的退化版本就是二分图最大匹配. 由于二分图中不存在奇环,偶环对最大匹配并无影响(可以调整).所以增广路算法是可以顺利应用的. 在一般图中,我们还是尝试使用BFS增广路的算法. 然而一般图中还会出现奇环,在寻找增广路的时候,怎么处理奇环上的冲突? 目的就是将奇环不断地缩起来(缩花),使得整个图在使用增广算法的时候不受影响,即不会经过奇环. ? ? ? 花 ? 一朵花由一个奇环缩点而成,一朵花里面可能还会有花.

kuangbin带你飞 匹配问题 二分匹配 + 二分图多重匹配 + 二分图最大权匹配 + 一般图匹配带花树

二分匹配:二分图的一些性质 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图. 1.一个二分图中的最大匹配数等于这个图中的最小点覆盖数 König定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数.如果你还不知道什么是最小点覆盖,我也在这里说一下:假如选

[kuangbin带你飞]专题十 匹配问题 一般图匹配

过去做的都是二分图匹配 即 同一个集合里的点 互相不联通 但是如果延伸到一般图上去 求一个一般图的最大匹配 就要用带花树来解决 带花树模板 用来处理一个无向图上的最大匹配 看了一会还是不懂  抄了一遍kuangbin的模板熟悉了一下 还有一个一般图最大权匹配 保存下来了VFK菊苣的模板题代码当作板子 http://uoj.ac/submission/16359 但愿以后的比赛永远也遇不到 .. 遇到了也能抄对 .. 抄错了也能过 .. R ural1099 kuangbin模板 #include