教练的礼物
总提交:39 测试通过:13
描述
南京邮电大学ACM程序设计竞赛校代表队成功晋级ACM/ICPC总决赛,教练老师非常高兴,特地从新西兰采购一批羊毛围巾和手套送出做出突出贡献的同学。但同学们各有所好,希望独自拥有一种型号的围巾或手套。请帮助教练老师分配这批礼物,使最多同学同时拥有自己喜欢的羊毛围巾和手套。
输入
第一行包括三个整数:N、C、D,分别表示做出突出贡献的同学人数、羊毛围巾的种类数、手套的种类数。 (1 ≤ N ≤ 100, 0 ≤ C ≤ 100,1 ≤ D ≤100)。
N行,每行对应一个同学对礼物的选择:
l 该同学所喜欢围巾的种类
l 该同学所喜欢手套的种类
l 该同学所喜欢围巾具体类型,依次给出类型号(以0,…,C表示)
l 该同学所喜欢手套具体类型,依次给出类型号(以0,…,D表示)
输出
一行,同时拥有自己所喜欢围巾和手套的最多同学人数。
注意:输出部分的结尾要求包含一个多余的空行。
样例输入
4 3 3
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3
样例输出
3
题目来源
“IBM南邮杯”个人赛2009
分析:网络最大流。此题很经典。关于网络流的算法需要多多理解!
关键在于构建模型:
源点(S)——围巾(C)建立一条边,流量为1
同学——喜欢的围巾(C)建立一条边,流量为1
同学——喜欢的手套(D)建立一条边,流量为1
手套(D)——汇点 (T)建立一条边,流量为1
关键:将学生的点拆开,在两端之间建立一条边,流量为1
求源点到汇点的最大流即为ans。因为每个人只能选择一个C和一个D。
我就采用了EK算法的模板。
int likeC[MAXN][MAXN];
int likeD[MAXN][MAXN];
int map[MAXN*4][MAXN*4];
int pre[MAXN*4];
queue<int> myque;
int N, C, D;
bool bfs(int src, int des)
{
memset(pre, -1, sizeof(pre));
while(!myque.empty()) myque.pop();
pre[src] = 0;
int index;
myque.push(src);
while(!myque.empty())
{
index = myque.front();
myque.pop();
for(int i=0;i<=des+1;i++) // des+1
{
if(pre[i] == -1 && map[index][i] > 0)
{
pre[i] = index;
if(i == des) return true;
myque.push(i);
}
}
}
return false;
}
int MaxFlow(int src, int des)
{
int maxflow = 0;
while(1)
{
if(!bfs(src, des)) break;
int i = des;
while(i != src)
{
map[pre[i]][i] -= 1;
map[i][pre[i]] += 1;
i = pre[i];
}
maxflow ++;
}
return maxflow;
}