最短路思想实现一般图最大匹配

考虑一下一般图和二分图的区别,无非就在于二分图可能出现长为奇数的环。

如何排除奇数环的影响???

最短路

设一般图中每条可匹配边长为1,该次匹配起点为v。

根据最短路定理,我们可以知道,v在带花树上到任意一个终点(即未匹配的点)的最短距离一定为奇数,且路径上一定不存在环。

那么,用广搜的方法去贪最短路的时候,贪出来的第一条路(即最短路)一定不含环。

设[1,n]代表S型点,[n+1,2*n]代表T型点,dist[i]表示v到i的最短路上经过的点数。

设ance[i][j]表示i的dist值为j的祖先的原编号,hash[i][j]表示j(原编号)是否是i的祖先。

那么i能拓展出j的充要条件就是(dist[i]+1<dist[j]&&!hash[i][j])

即满足最短路且满足非祖先关系。

通过广搜实现这个特殊图的最短路,从而得到一般图最大匹配。

代码如下,带上注释比我从网上找到的最短的带花树(不带注释)要短200字节

#include<cstdio>//O(n^3),神板子,码量不大
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;

const int maxl=99999999;
const int maxn=510;
int n,m,i,j,s,v,match[maxn],ance[maxn*2][maxn],dist[maxn*2],ans;
//[1,n]代表S型点,[n+1,2*n]代表T型点
//ance[i][j]表示i的dist为j的祖先的原编号,hash[i][j]表示j(原编号)是否是i的祖先
vector <int> l[maxn];
bool hash[maxn*2][maxn];

int z[maxn*2],r;
void change(int x){
	ans++;
	for (int i=dist[x];i>0;i-=2){
		match[ance[x][i]]=ance[x][i-1];
		match[ance[x][i-1]]=ance[x][i];
	}
}
void extend(int x){
	int i,j,k,v=(x>n?x-n:x);
	if (x>n){//若为T型点
		if (match[v]==0){//发现单身,增广
			change(x);return;
		}
		k=match[v];
		if (!hash[x][k]&&dist[k]>dist[x]+1){//十分类似于dijsktra的松弛操作
			dist[k]=dist[x]+1;
			for (j=1;j<=dist[x];j++)
				hash[k][ance[k][j]=ance[x][j]]=1;
			hash[k][ance[k][dist[k]]=k]=1;
			z[++r]=k;
		}
	}
	else
	for (i=0;i<(int)l[v].size();i++){//十分类似于dijsktra的松弛操作
		k=n+l[v][i];
		if (!hash[x][l[v][i]]&&dist[k]>dist[x]+1){
			dist[k]=dist[x]+1;
			for (j=1;j<=dist[x];j++)
				hash[k][ance[k][j]=ance[x][j]]=1;
			hash[k][ance[k][dist[k]]=l[v][i]]=1;
			z[++r]=k;
		}
	}
}
void bfs(int x){
	z[r=1]=x;						//初始化
	memset(ance,0,sizeof ance);
	memset(hash,0,sizeof hash);
	for (int i=1;i<=2*n;i++) dist[i]=maxl;
	dist[x]=hash[x][x]=1;
	ance[x][1]=x;
	for (int i=1;i<=r;i++){			//广搜
		extend(z[i]);
		if (match[x]!=0) return;
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	for (i=1;i<=m;i++){
		scanf("%d%d",&s,&v);
		l[s].push_back(v);
		l[v].push_back(s);
	}
	for (i=1;i<=n;i++)
	if (match[i]==0)
		bfs(i);
	printf("%d\n",ans);
	for (i=1;i<=n;i++) printf("%d ",match[i]);
	putchar(‘\n‘);
	return 0;
}
时间: 2024-08-08 01:25:26

最短路思想实现一般图最大匹配的相关文章

UOJ79 一般图最大匹配

题目描述 从前一个和谐的班级,所有人都是搞OI的.有 nn 个是男生,有 00 个是女生.男生编号分别为 1,-,n1,-,n. 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人负责吐槽.每个人至多属于一个小组. 有若干个这样的条件:第 vv 个男生和第 uu 个男生愿意组成小组. 请问这个班级里最多产生多少个小组? 输入格式 第一行两个正整数,n,mn,m.保证 n≥2n≥2. 接下来 mm 行,每行两个整数 v,uv,u 表示第 vv 个男生和第 uu 个男生愿意组成小

HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力

一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 如果C2+2==C1则这条边再某个最大匹配中 Boke and Tsukkomi Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Submission(s): 649    Accepted Submission(s): 202

HDU 5294--Tricks Device【最小割 &amp;&amp; 最短路处理,新建图】

Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2208    Accepted Submission(s): 584 Problem Description Innocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu's at the en

poj 3020 一般图最大匹配 带花树开花算法

题意: 给出一个h*w的图,每个点都是'o'或'*',最少要用多少个1*2的矩形才能把图中所有的'*'都覆盖掉. 限制: 1 <= h <= 40; 1 <= w <= 10 思路: 最小边覆盖=|V|-最大匹配 一般图最大匹配,带花树开花算法 /*poj 3020 一般图最大匹配 带花树开花算法 题意: 给出一个h*w的图,每个点都是'o'或'*',最少要用多少个1*2的矩形才能把图中所有的'*'都覆盖掉. 限制: 1 <= h <= 40; 1 <= w &l

It&amp;#39;s not a Bug, It&amp;#39;s a Feature! (poj 1482 最短路SPFA+隐式图+位运算)

Language: Default It's not a Bug, It's a Feature! Time Limit: 5000MS   Memory Limit: 30000K Total Submissions: 1353   Accepted: 516 Description It is a curious fact that consumers buying a new software product generally do not expect the software to

ZOJ 3316 Game 一般图最大匹配带花树

一般图最大匹配带花树: 建图后,计算最大匹配数. 如果有一个联通块不是完美匹配,先手就可以走那个没被匹配到的点,后手不论怎么走,都必然走到一个被匹配的点上,先手就可以顺着这个交错路走下去,最后一定是后手没有路可走,因为如果还有路可走,这一条交错路,就是一个增广路,必然有更大的匹配. Game Time Limit: 1 Second      Memory Limit: 32768 KB Fire and Lam are addicted to the game of Go recently.

[Usaco2007 Jan]Telephone Lines架设电话线[二分答案+最短路思想]

Description Farmer John打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务.于是,FJ必须为此向电信公司支付一定的费用. FJ的农场周围分布着N(1 <= N <= 1,000)根按1..N顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相连.一共P(1 <= P <= 10,000)对电话线杆间可以拉电话线,其余的那些由于隔得太远而无法被连接. 第i对电话线杆的两个端点分别为A_i.B_i,它们间的距离为 L_i (1 <= L_i

UOJ #79 一般图最大匹配

一般图最大匹配 从前一个和谐的班级,所有人都是搞OI的.有 \(n\) 个是男生,有 \(0\) 个是女生.男生编号分别为 \(1,-,n\). 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人负责吐槽.每个人至多属于一个小组. 有若干个这样的条件:第 \(v\) 个男生和第 \(u\) 个男生愿意组成小组. 请问这个班级里最多产生多少个小组? 输入格式 第一行两个正整数,\(n,m\).保证 \(n≥2\). 接下来 \(m\) 行,每行两个整数 \(v,u\) 表示第

HDU5669 Road 分层最短路+线段树建图

分析:(官方题解) 首先考虑暴力,显然可以直接每次O(n^2) ?的连边,最后跑一次分层图最短路就行了. 然后我们考虑优化一下这个连边的过程 ,因为都是区间上的操作,所以能够很明显的想到利用线段树来维护整个图, 连边时候找到对应区间,把线段树的节点之间连边.这样可以大大缩减边的规模,然后再跑分层图最短路就可以了. 但是这样建图,每一次加边都要在O(logn)个线段树节点上加边,虽然跑的非常快,但是复杂度仍然是不科学的. 为了解决边的规模的问题,开两棵线段树,连边时候可以新建一个中间节点,在对应区