BZOJ 1221 软件开发(网络流24题之餐巾规划)

来源:互联网 发布:机明石墨电极编程视频 编辑:程序博客网 时间:2024/06/10 12:34

解题思路:

  将每个点拆成两个,并建立一个源点S和一个汇点T。

  1. S到每个点 i 连一个容量为C费用为0 的边。

  2.每个点 i+N 到 T连一个容量为C费用为0的边。

  3.每个点 i 到 i+N 连一个容量为INF费用为 f 的边。

  4.每个点 i 到 i + a + 1 连一个容量为INF 费用为 fa 的边。

  5.每个点 i 到 i + b + 1 连一个容量为INF 费用为 fb 的边。

  6.每个点 i 到 i + 1  连一个容量为 INF 费用为 0 的边。

#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>#include <queue>#include <vector>#include <cmath>#define LL long longusing namespace std;const int maxn = 10000 + 10;const int INF = 100000;struct Edge{    int from,to,cap,flow,cost;    Edge(int u,int v,int c,int f,int w):from(u),to(v),cap(c),flow(f),cost(w) { }};int n;vector<Edge>edges;vector<int>G[maxn];int inq[maxn];int d[maxn];int p[maxn];int a[maxn];void init(){    for(int i=0;i<=n;i++)        G[i].clear();    edges.clear();}void AddEdge(int from,int to,int cap,int cost){    edges.push_back(Edge(from,to,cap,0,cost));    edges.push_back(Edge(to,from,0,0,-cost));    int M = edges.size();    G[from].push_back(M-2);    G[to].push_back(M-1);}bool SPFA(int s,int t,int& flow,LL& cost){    for(int i=0;i<=n+1;i++)        d[i] = INF;    memset(inq,0,sizeof(inq));    d[s] = 0;inq[s] = 1;p[s] = 0;a[s] = INF;    queue<int>Q;    Q.push(s);    while(!Q.empty())    {        int u = Q.front();Q.pop();        inq[u] = 0;        for(int i=0;i<G[u].size();i++)        {            Edge& e = edges[G[u][i]];            if(e.cap > e.flow && d[e.to] > d[u] + e.cost)            {                d[e.to] = d[u] + e.cost;                p[e.to] = G[u][i];                a[e.to] = min(a[u],e.cap-e.flow);                if(!inq[e.to]) {Q.push(e.to);inq[e.to] = 1;}            }        }    }    if(d[t] == INF) return false;    flow += a[t];    cost += (LL)d[t] * (LL)a[t];    for(int u=t;u!=s;u=edges[p[u]].from)    {        edges[p[u]].flow += a[t];        edges[p[u]^1].flow -= a[t];    }    return true;}int MincostMaxflow(int s,int t,LL &cost){    int flow = 0;cost = 0;    while(SPFA(s,t,flow,cost));    return flow;}int N,sd,fd,newn,sc,fc;int c;int main(){int i,c,newn,sd,sc,fd,fc;scanf("%d%d%d%d%d%d",&N,&sd,&fd,&newn,&sc,&fc);n = 2 * N + 1;init();int S=0 , T=N+N+1;for (i=1;i<=N;i++){scanf("%d",&c);AddEdge(S,i,c,0);AddEdge(i+N,T,c,0);AddEdge(S,i+N,INF,newn);if (i<N)AddEdge(i,i+1,INF,0);if (i+sd+1<=N)AddEdge(i,i+N+sd+1,INF,sc);if (i+fd+1<=N)AddEdge(i,i+N+fd+1,INF,fc);}LL cost = 0;MincostMaxflow(S,T,cost);cout<<cost<<endl;return 0;}

0 0