您的位置:首页 > 理论基础 > 计算机网络

POJ 3281 [网络流dinic算法模板]

2015-08-23 19:34 656 查看
题意:

农场主有f种食物,d种饮料,n头牛。

接下来的n行每行第一个数代表第i头牛喜欢吃的食物数量,和第i头牛喜欢喝的饮料数目。

接下来分别是喜欢的食物和饮料的编号。

求解:农场主最多能保证几头牛同时能吃到喜欢的食物和喜欢的饮料。

思路:

从源点到每种食物加流量为1的边,保证每种食物只能被吃一次。

将每头牛分为两个点,连一条流量为1的边,保证每头牛最多只能吃一份食物喝一份饮料。

将每种饮料和汇点都进行连接,同样流量为1。

将牛喜欢的食物和牛进行连边流量为1,将另一组代表牛的点和喜欢的饮料进行连边,同样流量为1。

建好图之后就变成了最大流问题了。

这里留一个用dinic解决最大流问题的模板。

/*************************************************************************
> File Name: T.cpp
> Author: ttpond
> Created Time: 2015-8-22 12:4:42
************************************************************************/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<set>
using namespace std;
int z;
int n,f,d;
int pho[405][405];
int dis[410];
int nb;
bool BFS()
{
nb++;
int i,j;
memset(dis,-1,sizeof(dis));
int tmp;
queue<int>q;
dis[1]=0;
q.push(1);
while(!q.empty())
{
tmp=q.front();
q.pop();
for(int i=1; i<=z; i++)
{
if(dis[i]<0&&pho[tmp][i])
{
dis[i]=dis[tmp]+1;
q.push(i);
}
}
}
if(dis[z]>0)
return 1;
else
return 0;
}
int findans(int x,int low)
{
int i,a=0;
if(x==z)
return low;
for(i=1; i<=z; i++)
{
if(pho[x][i]>0&&dis[i]==dis[x]+1&&(a=findans(i,min(low,pho[x][i]))))
{
pho[x][i]-=a;
pho[i][x]+=a;
return a;
}
}
return 0;
}
int main()
{
int a,b,tmp;
scanf("%d%d%d",&n,&f,&d);
z=2+f+n*2+d;
memset(pho,0,sizeof(pho));
for(int i=2; i<=1+f; i++)
{
pho[1][i]=1;
}
for(int i=f+2; i<=f+n+1; i++)
{
pho[i][i+n]=1;
}
for(int i=2+f+n*2; i<=1+f+n*2+d; i++)
{
pho[i][2+f+n*2+d]=1;
}
for(int i=1; i<=n; i++)
{
scanf("%d%d",&a,&b);
for(int j=1; j<=a; j++)
{
scanf("%d",&tmp);
pho[tmp+1][i+f+1]=1;
}
for(int j=1; j<=b; j++)
{
scanf("%d",&tmp);
pho[i+f+1+n][tmp+f+1+n*2]=1;
}
}
int ans=0,tans;
while(BFS())
{
while(tans=findans(1,0x7fffffff))
{
ans+=tans;
}
}
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: