题意
一共有N个学生跟P门课程,一个学生可以任意选一门或多门课,问是否达成:
1.每个学生代表的都是不同的课(如果一个学生选修的那门课,那么他就可以代表这门课)
2.每门课都有一个代表
输入为:
P N(课程数跟学生数)
接着有P行,格式为Count studenti studenti+1 ……studentcount
(Count表示对课程1感兴趣的学生数,接着有Count个学生)
如第一行2 1 2表示学生1跟学生2对课程1感兴趣
输出为:
若每门课都能找到一位代表则输出”YES”,否则为”NO”
匈牙利算法
增广路
增广路(也称增广轨或交错路): 若P是图G中一条连通两个未匹配顶点的路径,并且属M的边和不属M的边(即匹配边和非匹配边)在P上交替出现,则称P为相对于M的一条增广路径。
在图中,红边为三条边的匹配。路径x4→y3→x2→y1→x1→y2是一条交错路
由增广路的定义可以推出下述三个结论:
(1).P的路径长度必定为奇数,第一条边和最后一条边都不属于M,因为两个端点分属两个集合,且未匹配。
(2).P经过取反操作可以得到一个更大的匹配M’。
(3).M为G的最大匹配当且仅当不存在相对于M的增广路径。
找最大匹配的匈牙利算法流程
假如我们用xM数组表示左边节点对其右边节点的匹配,
yM表示右边节点对其左边节点的匹配,初始化为-1;
首先我们先看节点1,寻找下一条边,假设找到节点5,因为1跟5都还没匹配,所以找到一个匹配.标记,xM[1]=5,yM[5]=1;
现在重点看节点3,当寻找下一条边时,如图中的蓝边,我们发现节点6的yM[6]=2;已经匹配了.
此时我们就转到节点6的匹配点2上去,发现节点2的另一条边2->5中节点5也已经匹配了,yM[5]=1;继续转到节点1,发现节点1的边1->4中节点4还没匹配.于是我们找到了一个增广路径
算法流程
所以流程就是:
1,对于一个未匹配的节点u,寻找它的每条边,如果它的边上的另一个节点v还没匹配则表明找到了一个匹配,直接转步骤4;
2,假如节点u它边上的另一个节点v已经匹配,那么就转向跟v匹配的节点,假设是w,然后再对w重复1,2的步骤,即寻找增广路.
3,假如我们在1,2步过程中找到一条增广路, 那么修改各自对应的匹配点,转步骤4,若无增广路, 则退出.
4,匹配数+1;
本题参考代码
#include<iostream>
#include<vector>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define