【海岛帝国系列赛】No.7 海岛帝国:神圣之日
50237242海岛帝国:神圣之日
【试题描述】
战争持续九个月了。“购物券”WHT的军队还在跟恐怖分子僵持着。WHT和LJX已经向“公务员”告急,情况不宜乐观。YSF为守护帝国决定打开“够累 的”星际仓库来化解恐怖分子的威胁。他和LTJ、WHT、LJX、YSM、LYF等人来到了传说中的星际仓库的防爆门前。“郭同学”TONY,“演 员”KLINT,“美的”STEVE……都被恐怖分子的间谍困在里面。由于情况复杂,恐怖分子在门上加了一层层密码,如果没有顺利答对,“蝴蝶”将会引 爆。整个城市将毁灭。门上有这样一幅图,一排有两个空位,地下散落着N枚“微型机器人”其中编号1,2,3表示TX型号(呵呵呵,大家都知道“州长” 吧)4,5,6表示T-5000型号,每排必须有TX、T-5000型号各一个。当把两个机器人插在一排时,如果这两个机器人互相感应就会亮起红灯。要求 尽量让有感应的机器人插在一起。请问如何摆放,才能让最多的机器人满足条件?
【输入要求】
* 第一行两个正整数N,M,表示有N个机器人,有M个关系道
* 接下来M行:每行两个数A,B表示机器人A和B之间有感应
【输出要求】
* 一行:表示能满足的最大值
【输入实例】
6 5
1 4
1 5
2 5
2 6
3 4
【输出实例】
3
【其他说明】
依旧,
M均小于40
N均小于10
【试题分析】
这里用到了二分图匹配,所以我们先来了解一下,什么是二分图。
简而言之,就是顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集,两个子集内的顶点不相邻。
最大匹配
编辑算法
1 最大匹配
在G的一个子图M中,M的边集中的任意两条边都不依附于同一个顶点,则称M是一个匹配。选择这样的边数最大的子集称为图的最大匹配问题,最大匹配的边数称
为最大匹配数.如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备匹配。如果在左右两边加上源汇点后,图G等价于一
个网络流,最大匹配问题可以转为最大流的问题。解决此问的匈牙利算法的本质就是寻找最大流的增广路径。上图中的最大匹配如下图红边所示:
2 最优匹配
最优匹配又称为带权最大匹配,是指在带有权值边的二分图中,求一个匹配使得匹配边上的权值和最大。一般X和Y集合顶点个数相同,最优匹配也是一个完备匹配,即每个顶点都被匹配。如果个数不相等,可以通过补点加0边实现转化。一般使用KM算法解决该问题。
3 最小覆盖
二分图的最小覆盖分为最小顶点覆盖和最小路径覆盖:
①最小顶点覆盖是指最少的顶点数使得二分图G中的每条边都至少与其中一个点相关联,二分图的最小顶点覆盖数=二分图的最大匹配数;
②最小路径覆盖也称为最小边覆盖,是指用尽量少的不相交简单路径覆盖二分图中的所有顶点。二分图的最小路径覆盖数=|V|-二分图的最大匹配数;
4 最大独立集
最大独立集是指寻找一个点集,使得其中任意两点在图中无对应边。对于一般图来说,最大独立集是一个NP完全问题,对于二分图来说最大独立集=|V|-二分图的最大匹配数。如下图中黑色点即为一个最大独立集:
设G=(V,E)是一个无向图。如顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属两个不同的子集。则称图G为二分图。也就是说在二分图中,顶点可以分为两个集
X和Y,每一条边的两个顶点都分别位于X和Y集合中。
【以上内容为转载】
求二分图最大匹配的方法最容易想到的就是找出全部匹配,然后输出配对数最多的。但这种方法的时间复杂度非常高,那么,有没有更好的方法呢?
当然,如果找到一条增广路,那么配对数就会加一,它的本质就是一条路径的起点和终点都是未配对的点。如果在当下再也找不到增广路,那么当前就是最大匹配了。
【代码】
1 #include<iostream> 2 using namespace std; 3 int e[101][101]; 4 int match[101]; 5 int book[101]; 6 int n,m; 7 int dfs(int u) 8 { 9 int i; 10 for(i=1;i<=n;i++) 11 if(book[i]==0&&e[u][i]==1) 12 { 13 book[i]=1; 14 if(match[i]==0||dfs(match[i])) 15 { 16 match[i]=u; 17 match[u]=i; 18 return 1; 19 } 20 } 21 return 0; 22 } 23 int main() 24 { 25 int i,j,t1,t2,sum=0; 26 scanf("%d%d",&n,&m); 27 for(int i=1;i<=m;i++) 28 { 29 cin>>t1>>t2; 30 e[t1][t2]=1; 31 e[t2][t1]=1; 32 } 33 for(i=1;i<=n;i++) match[i]=0; 34 for(i=1;i<=n;i++) 35 { 36 for(j=1;j<=n;j++) book[j]=0; 37 if(dfs(i)) sum++; 38 } 39 printf("%d",sum); 40 }