poj 1149 PIGS

本文介绍了一种利用最大流算法解决特定问题的方法:即给定若干猪圈及其中的猪的数量,以及一系列顾客能打开某些猪圈并购买一定数量猪的情况,通过构建最大流图模型来确定一天内最多能卖出多少猪。文章详细描述了如何构造图模型,并使用 Edmonds-Karp 算法求解最大流。
摘要由CSDN通过智能技术生成
最大流:
题意:给你m个猪圈以及每个猪圈里原来有多少头猪,先后给你n个人,每个人能打开一些猪圈并且他们最多想买Ki头猪,在每一个人买完后能将打开的猪圈中的猪顺意分配在这次打开猪圈里,在下一个人来之前 已打开的猪圈被锁上。问这个人一天最多卖出多少猪。
建立超级源点和第一个打开某个猪圈的人相连,权值为它打开的猪圈的初始猪的头数,当一个人有多把钥匙时,权值可以合并。
接下来打开猪圈的人和第一个打开猪圈的人相连,权值为inf。
建立超级汇点和每一个人相连,权值为他能购买猪的上限。
建好图后,就是裸的最大流算法了,我用的EK。



#include<math.h>
#include<stdio.h>  
#include<string.h>  
#include<iostream>   
#define M 1100
#define inf 100000000
int map[M][M];
int pre[M],queue[M],pig[M],buy[M],vis[M];
int flow,start,end,tot,ans,owner[M];  
using namespace std;  
int bfs()  
{  
    int p=0,q=1;  
    queue[0]=1;  
    flow=inf;  
    memset(pre,-1,sizeof(pre));  
    while(p<q)  
    {  
       int s=queue[++p];  
       for(int i=1;i<=end;i++)  
       {  
          if(pre[i]==-1&&map[s][i]>0)  
          {  
             pre[i]=s;  
             flow=min(flow,map[s][i]);  
             queue[++q]=i;  
             if(i==end) return flow;  
          }  
       }  
    }  
    return -1;  
}  
int Edmonds_Karp()  
{  
    tot=0;  
    while((ans=bfs())!=-1)  
    {  
        tot+=ans;  
        int now=end; 
        while(now!=0)  
        {  
            map[pre[now]][now]-=ans;  
            map[now][pre[now]]+=ans;  
            now=pre[now]; 
        }  
    }  
    return tot;  
}  
int main()
{
     int n,m,i,j,num,temp;
     while(scanf("%d%d",&m,&n)!=EOF)
     {
         for(i=1;i<=m;i++)
             scanf("%d",&pig[i]);
         memset(vis,0,sizeof(vis));
         memset(map,0,sizeof(map));
         for(j=1;j<=n;j++)
         {
             scanf("%d",&num);
             while(num--)
              {
                scanf("%d",&temp);
                 if(vis[temp]==0)
                     map[0][j]+=pig[temp],vis[temp]=j;
                 else
                     map[vis[temp]][j]=inf;
              }
             scanf("%d",&temp);
             map[j][n+1]=temp;
        }
        start=0,end=n+1;
        printf("%d\n",Edmonds_Karp());  

     }
     return 0;
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值