这几天在琢磨着二分图的问题,二分图是图论算法中很基本的一个问题,其本身有很多的变种问题,二分图最大匹配,最小顶点覆盖,最小路径覆盖,最大独立集等等,但是万变不离其宗,其本质我发现最后都可以用一个模板解决。下面就说下我学习二分图的步骤。至于二分图的概念,大家应该已经知道,不再赘述,或者自行百度。
二分图问题一般有两种算法:最大网络流算法,匈牙利算法。至于前者,网络流问题我一直认为是图论中的难点,准备放在最后学习。而后者是适合于新手的一种算法。这里我选择的自然是匈牙利算法。
由hdu2063过山车问题引入,详解请参考请参考我的博文——二分图最大匹配。问题大概就是在说男生一边,女生一边,然后有些女生只会选择他们心仪的几个男生一起坐过山车(丑的人就没妹子了),理解为一夫一妻。很显然的一个二分图,问最多能有多少对男女能一起坐过山车。简单附上模板:
#define N 510 int useif[N]; //记录y中节点是否使用 0表示没有访问过,1为访问过 int link[N]; //记录当前与y节点相连的x的节点 int mat[N][N]; //记录连接x和y的边,如果i和j之间有边则为1,否则为0 int gn,gm; //二分图中x和y中点的数目 bool can(int t) { int i; for(i=1;i<=gm;i++) { if(useif[i]==false && mat[t][i]) { useif[i]=true; if(link[i]==-1 || can(link[i])) { link[i]=t; return true; } } } return false; } int MaxMatch() { int i,num; num=0; memset(link,0xff,sizeof(link)); for(i=1;i<=gn;i++) { memset(useif,0,sizeof(useif)); if(can(i)) num++; } return num; }
在二分图中求最少的点,让每条边都至少和其中的一个点关联,这就是:“二分图的最小顶点覆盖”求最少的点,让每条边都至少和其中的一
二分图的最小顶点覆盖数=最大匹配数
引入例题hdu1150
题目大意:
有两台机器A和B以及N个需要运行的任务。每台机器有M种不同的模式,而每个任务都恰好在一台机器上运行。
如果它在机器A上运行,则机器A需要设置为模式xi,如果它在机器B上运行,则机器A需要设置为模式yi。
每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式需要重启一次。请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少。
怎么解决呢?首先确定这是一个满足二分图定义的题目,下面才会发现着属于最小顶点覆盖。之前已经做过二分图最大匹配了,这个题目就可以理解为求最大匹配数,因为已经有结论:二分图的最小顶点覆盖数=最大匹配数。
稍微改动一下输入格式就可以AC了。
题目大意:
在一个城镇,有m个路口,和n条路,这些路都是单向的,而且路不会形成环,现在要弄一些伞兵去巡查这个城镇,
伞兵只能沿着路的方向走,问最少需要多少伞兵才能把所有的路口搜一遍。这个题目就转换成求解有向无环图的最
小路径覆盖问题了。
也是做一些输入的修改后直接套用模板。