前述:这周还是在看图论的知识,顺着饶齐的博客基本把最大流的题都做完了,开了一下二分图最大匹配的专题(就是借个专题网址,除了刚开始做网络流的那两个模板题,把三个版本的优秀写法全部借鉴进来的时候看了一下题解,后来就没法看了,因为码风都不一样,但是出奇的顺利,网络流如果不是分点的题我在知道这个题是网络流的前提下可以快速想出来构图并ac而且基本1a,达到我预想的效果了,所以开了新的专题。)基本就是这样了,现在没有专题的引导了,队友正好也搬到了一个楼,所以经常一起a题共勉吧,基本都是约好时间做题。
题目:
题目大意:已知n个学生,m门课,告诉你每门课对应的想选这门课的学生有谁,然后问是否存在一个方案使得每门课都恰好有一个学生选。
解题思路:就是个裸的二分图最大匹配,最大匹配若等于课程的总数,就说明存在这个方案。(这个题基本抄的题解,因为是专题的开端还有就是对以前学习的复习,发现实际操作的时候有很多理解的问题,比如:1.二分图不是一个双向匹配,就是由左到右的匹配一般不等于从右到左的匹配。2.后来做了几个题发现,这种题的给出方式都特别明显的显示出了匹配的方向,这就更需要对方向理解深刻才能知道到底是在匹配什么,比如这个题,就是给课程选学生,如果学生选课,就是完全不同的结果。3.vector写法虽然省时间,但是和邻接表有一处很不相同)总之也算是吃了不少苦头,poj还卡的要命,单还是把它a了。
AC代码:
#include<iostream>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;
int n,m;
vector<int>map[110];
bool visit[310];
int cx[110];
int cy[310];
bool dfs(int x){
int i,j;
for (i=0;i<map[x].size();i++){
j=map[x][i];
if (visit[j]==0){
visit[j]=1;
if (cy[j]==-1||dfs(cy[j])){
cy[j]=x;
cx[x]=i;
return 1;
}
}
}
return 0;
}
int maxmatch(){
int i,j,ans=0;
memset (cx,-1,sizeof(cx));
memset (cy,-1,sizeof(cy));
for (i=0;i<m;i++){
if (cx[i]==-1){
memset (visit,0,sizeof(visit));
ans+=dfs(i);
}
}
return ans;
}
int main(){
int T,i,j,x,y;
bool flag;
scanf("%d",&T);
while (T--){
flag=1;
scanf("%d%d",&m,&n);
for (i=0;i<m;i++){
map[i].clear();
}
for (i=0;i<m;i++){
scanf("%d",&x);
if (x==0)flag=0;
for (j=0;j<x;j++){
scanf("%d",&y);
map[i].push_back(y);
}
}
if (flag==0)printf("NO\n");
else {
int ans=maxmatch();
if (ans==m)printf("YES\n");
else printf("NO\n");
}
}
}