题目链接
题目大意:奶牛喜欢一些种类的食物和饮料,给n种食物,m种饮料,问最多能喂多少奶牛(每种食物和饮料只能使用一次)
思路:把奶牛,食物,饮料都看做点,为了保证路线合法性,奶牛需要在中间,向2边构图。奶牛需要拆点。
emmmm如果奶牛喜欢三样东西应该怎么构图?
#include <bits/stdc++.h>
using namespace std;
const int N = 110*4;
const int M = N*N;
int n,m,s,t,tot;
int head[N];
struct node{
int u,nxt,cap,to;
}edge[M<<1];
int cur[N],deep[N];
void ae(int u,int v,int w){
tot++;
edge[tot].nxt = head[u];
edge[tot].to = v;
edge[tot].u = u;
edge[tot].cap = w;
head[u] = tot;
}
bool bfs(){
memset(deep,-1,sizeof(deep));
queue<int>q;
q.push(s);
deep[s] = 0;
while(!q.empty()){
int u = q.front();
for(int i = head[u]; ~i;i = edge[i].nxt){
int v = edge[i].to;
if(deep[v]==-1&&edge[i].cap>0){
q.push(v);
deep[v] = deep[u]+1;
if(v==t) return 1;
}
}
q.pop();
}
return 0;
}
int dfs(int u,int f){
int flow = 0,d;
if(u==t||f==0) return f;
for(int &i = cur[u]; ~i;i = edge[i].nxt){
int v = edge[i].to;
if(deep[v]>deep[u]&&edge[i].cap>0&&(d=dfs(v,min(f,edge[i].cap)))){
edge[i].cap -= d;
edge[i^1].cap += d;
f -= d;
flow += d;
if(!f) break;
}
}
if(flow==0) deep[u] = -1;
return flow;
}
int dinic(){
int ans = 0;
while(bfs()){
memcpy(cur, head, sizeof(head));
ans += dfs(s,1e9);
}
return ans;
}
int main()
{
//freopen("a.txt","r",stdin);
ios::sync_with_stdio(0);
int n1,n2,n3;
cin>>n2>>n1>>n3;
s = 0;
t = n1+n2*2+n3+1;
memset(head,-1,sizeof(head));
tot = -1;
int i,j;
for(i = 1;i <= n1;i ++){
ae(0,i,1); //s连食物
ae(i,0,0);
}
for(i = n1+n2*2+1;i <= n1+n2*2+n3;i ++){
ae(i,t,1); //饮料连t
ae(t,i,0);
}
for(i = 1;i <= n2;i ++){
ae(n1+i,n1+i+n2,1); //奶牛拆点
ae(n1+i+n2,n1+i,0);
int num1,num2;
cin>>num1>>num2;
for(j = 1;j <= num1;j ++){
int x;
cin>>x;
ae(x,n1+i,1); //奶牛连食物
ae(n1+i,x,0);
}
for(j = 1;j <= num2;j ++){
int x;
cin>>x;
ae(n1+i+n2,n1+n2*2+x,1); //奶牛连饮料
ae(n1+n2*2+x,n1+i+n2,0);
}
}
cout<<dinic();
return 0;
}