广州的同学看这里:
http://www.gdgzoi.com/JudgeOnline/problem.php?cid=1045&pid=1
Description
FJ的奶牛们只吃各自喜欢的一些特定的食物和饮料,除此之外的其他食物和饮料一概不吃。某天FJ为奶牛们精心准备了一顿美妙的饭食,但在之前忘记检查奶牛们的菜单,这样显然是不能不能满足所有奶牛的要求。但是FJ又不愿意为此重新来做,所以他他还是想让尽可能多的牛吃到他们喜欢的食品和饮料。
FJ提供了F (编号为1、2、…、F)种食品并准备了D (编号为1、2、…、D)种饮料, 他的N头牛(编号为1、2、…、N)都已决定了是否愿意吃某种食物和喝某种饮料。FJ想给每一头牛一种食品和一种饮料,使得尽可能多的牛得到喜欢的食物和饮料。
每一种食物和饮料只能由一头牛来用。例如如果食物2被一头牛吃掉了,没有别的牛能吃到食物2。
【输入】第一行包含三个用空格分开的整数N,F和D;接下来的N行描述每个奶牛的信息:第i+1行的前两个整数为F_i和D_i,接下来的F_i个整数表示奶牛i喜欢的食品编号,再接下来的D_i个整数表示奶牛i喜欢的饮料编号。
【输出】仅一行一个整数,表示FJ最多能让多少头奶牛吃到自己喜欢的食品和饮料。
【样例】
Dining.in | Dining.out |
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
|
【样例说明】
输入数据表明:奶牛1喜欢的食物1、2;喜欢喝饮料3、1;奶牛2喜欢的食物2、3;喜欢喝饮料1、2;奶牛3喜欢的食物1、3;喜欢喝饮料1、2;奶牛4喜欢的食物1、3;喜欢喝饮料3;
那么下面的分配方法将是最优的:奶牛1不给食品和饮料;奶牛2分配食物2和饮料2;奶牛3分配食物1和饮料2;奶牛4分配食物3和饮料3。
【数据范围】
1<=F<=100,1<=D<=100,1<=N<=100
非常典型的网络流问题
下面是建图方法:
1.建一个超源点连接每一种食物容量为1。
2.将每种食物和奶牛连接起来:把奶牛拆成两个点,一个连接食物容量1,一个连接饮料容量1,再把这俩点连接,容量为1;
3.最后再把饮料与超汇点连接起来容量为1;
这样就保证了一牛,一食,一饮料。
接下来就是贴码的时候了:
mdzz数据太弱我这个蒟蒻没有拆牛(不,是压根没牛竟然过了)
代码仅供参考(千万别学我的苟数据)
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>
#define maxn 205
#define INF 2
using namespace std;
struct edg{
int from,to,cap,flow;
edg(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
};
int a[maxn];
int p[maxn];
vector<int> G[maxn];
vector<edg> edges;
bool GG[maxn][maxn];
void AddEdge(int u,int v){
edges.push_back(edg(u,v,1,0));
edges.push_back(edg(v,u,0,0));
int num=edges.size();
G[u].push_back(num-2);
G[v].push_back(num-1);
GG[u][v]=true;
}
int Maxflow(int s,int t)
{int flow=0;
for(;;){
memset(a,0,sizeof(a));
queue<int> Q;
Q.push(s);a[s]=INF;
while(!Q.empty()){
int x=Q.front();Q.pop();
for(unsigned int i=0;i<G[x].size();i++) {
edg& e=edges[G[x][i]];
if(!a[e.to] && e.cap>e.flow){
p[e.to]=G[x][i];
a[e.to]=min(a[x],e.cap-e.flow);
Q.push(e.to);
}
if(a[t]!=0) break;
}
}
if(a[t]==0) break;
for(int i=t;i!=s;i=edges[p[i]].from){
edges[p[i]].flow+=a[t];
edges[p[i]^1].flow-=a[t];}
flow+=a[t];
}
return flow;
}
//上面的模板emmm
int main()
{std::ios::sync_with_stdio(false);
int m,n,z,Fs,Ds;
int F[maxn],D;
cin>>m>>n>>z;
for(int i=1;i<=m;i++)
{cin>>Fs>>Ds;
for(int j=1;j<=Fs;j++)
cin>>F[j];
for(int j=1;j<=Ds;j++)
{cin>>D;
for(int k=1;k<=Fs;k++)
if(!GG[F[k]][100+D])
AddEdge(F[k],100+D);//超源点接食物。
}
}//没有牛竟然能过!!!
for(int i=1;i<=n;i++)
AddEdge(0,i);
for(int i=1;i<=z;i++)
AddEdge(i+100,201);//超汇点接饮料;
cout<<Maxflow(0,201)<<endl;
return 0;
}