[二分图最大匹配]
题目大意
完美的牛栏 农夫约翰上个星期刚刚建好了他的新牛棚,他使用了新的挤奶技术.不幸的是,由于工程问题,每 个牛栏都不一样.第一个星期,农夫约翰随便地让奶牛们进入牛栏,但是问题很快地显露出来:每头 奶牛都只愿意在她们喜欢的那些牛栏中产奶.上个星期,农夫约翰刚刚收集到了奶牛们的爱好的信 息(每头奶牛喜欢在哪些牛栏产奶).一个牛栏只能容纳一头奶牛,当然,一头奶牛只能在一个牛栏 中产奶. 给出奶牛们的爱好的信息,计算大分配方案.
PROGRAM NAME: stall4
INPUT FORMAT
第一行 两个整数,N (0 <= N <= 200) 和 M (0 <= M <= 200) .N 是农夫约翰的奶牛数量,M 是 新牛棚的牛栏数量.
第二行到第 N+1 行 一共 N 行,每行对应一只奶牛.第一个数字 (Si) 是这头奶牛愿意在其中产奶 的牛栏的数目 (0 <= Si <= M) .后面的 Si 个数表示这些牛栏的编号.牛栏的编号限定在区间 (1..M) 中,在同一行,一个牛栏不会被列出两次.
SAMPLE INPUT (file stall4.in)
5 5
2 2 5
3 2 3 4
2 1 5
3 1 2 5
1 2
OUTPUT FORMAT
只有一行.输出一个整数,表示多能分配到的牛栏的数量.
SAMPLE OUTPUT (file stall4.out)
4
[题目思路:就是二分图的最大匹配]
不懂二分图的戳这里
/*
ID:***
TASK:stall4
LANG:C++
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define cle(x) memset(x,0,sizeof(x))
const int N=205;
int n,m;
struct ii{
int to,ne;
ii(int to=0,int ne=0):to(to),ne(ne){ }
}ed[N*N*2];
int head[N];
bool used[N];//左边的点访问过没有
int match[N];//左边点的匹配点
bool crosspath(int u){
for(int i = head[u];i;i=ed[i].ne){
int v=ed[i].to;
if(!used[v]){
used[v]=true;//左边的点为u,找到右边的点,不是以右边的点进行dfs,而是以右边的匹配点进行dfs
if(match[v]==0||crosspath(match[v])){
//匹配的开始和结束一定是以match[i]=0,因为增广路的端点都是未盖点
match[v]=u;
return true;
}
}
}
return false;
}
int match_sum,tot;
void hungary(){
for(int i = 1; i <= n; i++){
cle(used);//每一次都要清空去dfs
if(crosspath(i))match_sum++;
}
}
int main(){
freopen("stall4.in","r",stdin);
freopen("stall4.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i = 1; i<= n; i++){
int q;
scanf("%d",&q);
for(int j = 1; j<= q; j++){
int v;
scanf("%d",&v);
ed[++tot]=ii(v,heai]);
head[i]=tot;
}//只需要存单向边,
}
hungary(
);
printf("%d\n",match_sum);
}
个人认为那个友链讲的很好,。。。
要数据的评论哦,,