给出牛,饮料还有食物的数量,每头牛给出喜欢的饮料和食物,最后求出能够满足的牛的数量
看别人的算法,把牛分解成两个点,然后按照 饮料-牛1-牛1-食物的对应关系进行计算最大网络流,这样形成了多源点多汇点的最大流
如果这个点不分解的话,为什么不行?纠结...
后来想明白了,如果不把牛拆开的话,多个饮料会对应到一头牛上,并且这头牛如果再对应到另外的食物的话,也可算是增广路,但是已经不符合条件了
所以把牛拆开加一条1的路,可以限制每头牛只能对应一个饮料
先放上代码,回头思考
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string.h>
#include <queue>
#include <limits.h>
#define MAX 500
using namespace std;
int n,f,d;
int cap[MAX][MAX];
int EKarp(int s,int t)
{
queue<int> Q;
int a[MAX],flow[MAX][MAX],pre[MAX];
int f = 0,u,v;
memset(flow,0,sizeof(flow));
while(1)
{
memset(a,0,sizeof(a));
a[s] = INT_MAX;
Q.push(s);
while( !Q.empty() )
{
u = Q.front();
Q.pop();
for(v=s; v<=t; v++)
if( !a[v] && cap[u][v] > flow[u][v] )
{
Q.push(v);
a[v] = a[u] < cap[u][v] - flow[u][v] ? a[u] : cap[u][v] - flow[u][v];
pre[v] = u;
}
}
if( a[t] == 0 )
break;
for(u=t; u!=s; u=pre[u])
{
flow[pre[u]][u] += a[t];
flow[u][pre[u]] -= a[t];
}
f += a[t];
}
return f;
}
int main()
{
int ff,dd,ans,i;
int food,drink;
while( scanf("%d%d%d",&n,&f,&d) != EOF )
{
memset(cap,0,sizeof(cap));
for(i=1; i<=n; i++)
{
scanf("%d%d",&ff,&dd);
cap[i][i+n] = 1;
while( ff-- )
{
scanf("%d",&food);
cap[2*n+food][i] = 1;
}
while( dd-- )
{
scanf("%d",&drink);
cap[i+n][2*n+f+drink] = 1;
}
}
for(i=2*n+1; i<=2*n+f; i++)
cap[0][i] = 1;
for(i=2*n+f+1; i<=2*n+f+d; i++)
cap[i][2*n+f+d+1] = 1;
ans = EKarp(0,2*n+f+d+1);
printf("%d\n",ans);
}
return 0;
}

浙公网安备 33010602011771号