码迷,mamicode.com
首页 > 其他好文 > 详细

网络流补强计划.....

时间:2015-10-07 01:04:01      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:

Poj 1149(最大流建图

题目:有m个猪圈,n个顾客,n个顾客依次到达,每个顾客可以打开若干个猪圈,可以选择给当前顾客卖不超过b头猪,并且当前打开的猪圈中的猪可以任意调整。问最多能卖多少猪。

思路:首先是直观的建图,由于有顺序关系,所以考虑给每个顾客建一层图,那么节点数就是n×m,这个数目太大。可以注意到原图中有很多OO权的边,比如可以相互转移的猪圈之间的边。这些边是可以化简的。具体化简思路见http://ycool.com/post/zhhrrm6#pic1

化简之后的图即为:原点向每个猪圈的第一个顾客连边,流量为猪圈里猪的数目。每个顾客向下一个到达这个猪圈的顾客连无穷的边。顾客向汇点连边。

理解:首先这么建图体现了顺序性,每个顾客的可选的猪的数目与前一个到猪圈的顾客选了多少有关。分配方面,每个顾客都和所有的来源连边了,并且流过来的流量是前面决策之后的。

化简的重点是来源,去向。后到的顾客可选的是前面的顾客选剩下的。

技术分享
/*
* @author:  Cwind
*/
///#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-6)
#define IINF (1<<29)
#define LINF (1ll<<59)
#define INF (1000000000)
#define FINF (1e3)
#define clr(x) memset((x),0,sizeof (x));
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> P;

const int maxv=100000;
struct EDGE{
    int to,cap,rev;
    EDGE(int t,int c,int r):to(t),cap(c),rev(r){}
};
vector<EDGE> G[maxv];
void addedge(int from,int to,int cap){///加边
    G[from].pb(EDGE(to,cap,G[to].size()));
    G[to].pb(EDGE(from,0,G[from].size()-1));
}
int s=maxv-1;
int t=maxv-2;
int level[maxv];
queue<int> Q;
void bfs(int s){////bfs出分层图
    memset(level,-1,sizeof level);
    level[s]=0;
    Q.push(s);
    while(!Q.empty()){
        int v=Q.front();Q.pop();
        for(int i=0;i<G[v].size();i++){
            EDGE &e=G[v][i];
            if(e.cap>0&&level[e.to]==-1){
                level[e.to]=level[v]+1;
                Q.push(e.to);
            }
        }
    }
}
int iter[maxv];
int dfs(int v,int t,int f){///dfs寻找增广路径
    if(v==t) return f;
    for(int &i=iter[v];i<G[v].size();i++){
        EDGE &e=G[v][i];
        if(e.cap>0&&level[e.to]>level[v]){
            int d=dfs(e.to,t,min(f,e.cap));
            if(d>0){
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}
int dinic(int s,int t){///dinic算法求解最大流
    int flow=0;
    for(;;){
        bfs(s);
        if(level[t]==-1) return flow;
        memset(iter,0,sizeof iter);
        int f;
        while((f=dfs(s,t,IINF))>0) flow+=f;
    }
    return 0;
}

const int maxn=2000;
vector<int> cus[maxn];
int pig[maxn];
int need[maxn];
int n,m;
void build(){
    for(int i=1;i<=m;i++){
        if(cus[i].size()){
            addedge(s,cus[i][0],pig[i]);
        }
        for(int j=1;j<cus[i].size();j++){
            addedge(cus[i][j-1],cus[i][j],INF);
        }
    }
    for(int i=1;i<=n;i++){
        addedge(i,t,need[i]);
    }
}
int main(){
    freopen("/home/slyfc/CppFiles/in","r",stdin);
    cin>>m>>n;
    for(int i=1;i<=m;i++){
        scanf("%d",&pig[i]);
    }
    for(int i=1;i<=n;i++){
        int a;
        scanf("%d",&a);
        for(int j=0;j<a;j++){
            int k;
            scanf("%d",&k);
            cus[k].pb(i);
        }
        scanf("%d",&need[i]);
    }
    build();
    printf("%d",dinic(s,t));
    return 0;
}
View Code

 

网络流补强计划.....

标签:

原文地址:http://www.cnblogs.com/Cw-trip/p/4858067.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!