poj1149PIGS 最大流

自己的第一道最大流,还是要纪念一下的。


题目连接poj1149


转化成网络流即可。将顾客看成除了源点和汇点以外的其他节点,再添加源点和汇点即可。

因为只要猪圈打开了猪就可以任意调整,所以相对同一个猪圈,后打开的人从猪圈里买到的猪的理论值为无限大。源点和打开猪圈第一人之间的容量为这个猪圈内住的数量。顾客节点和汇点的容量为顾客需要购,买猪的数量。构造网络,求源点到汇点的最大流。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 30000000
#define maxn 105
using namespace std;


int map[maxn][maxn];
int p[maxn];
int s,t,n;
int N,M;




//求最大流模板
bool bfs(int start,int end){
    bool flag[maxn];
    memset(p,-1,sizeof(p));
    memset(flag,0,sizeof(flag));
    queue<int> que;
    que.push(start);
    flag[start]=1;
    while(!que.empty()){
        int e=que.front();
        if(e==end) return true;
        que.pop();
        for(int i=0;i<=N+1;i++){
            if(map[e][i]&&!flag[i]){
                flag[i]=1;
                p[i]=e;
                que.push(i);
            }
        }
    }
    return false;
}


int EK(int start,int end){
    int u,flow=0,mn;
    while(bfs(start,end)){
        mn=INF;
        u=end;
        while(p[u]!=-1){
            mn=min(mn,map[p[u]][u]);
            u=p[u];
        }
        u=end;
        flow+=mn;
        while(p[u]!=-1){
            map[p[u]][u]-=mn;
            map[u][p[u]]+=mn;
            u=p[u];
        }
    }
    return flow;
}


//初始化
void init(){
    int num;
    int k;
    int house[1010];
    int last[1010];
    memset(last,0,sizeof(last));
    memset(map,0,sizeof(map));
    scanf("%d%d",&M,&N);
    s=0;
    t=N+1;
    for(int i=1;i<=M;++i) scanf("%d",&house[i]);
    for(int i=1;i<=N;++i){
        scanf("%d",&num);
        for(int j=0;j<num;++j){
            scanf("%d",&k);
            if(last[k]==0) map[s][i]+=house[k];
            else map[last[k]][i]=INF;
            last[k]=i;
        }
        scanf("%d",&map[i][t]);
    }
    /*
    for(int i=0;i<=N+1;++i){
        for(int j=0;j<=N+1;++j) cout<<map[i][j]<<" ";
        cout<<endl;
    }
    */
}


int main()
{
    init();
    cout<<EK(s,t)<<endl;
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值