洛谷P1251:网络流24题——餐巾计划问题

来源:互联网 发布:linux安装扫描漏洞 编辑:程序博客网 时间:2024/06/14 14:25

这题用zkw是真的快……洛谷原先是卡了普通费用流的……但是现在时间到4s了,又有o2和高性能,貌似普通的费用流也可以过了,首先,要把每一天和源点汇点建一条容量为每天的需求的边,费用为0,然后在条件满足的情况下(i + n < num of days之类的),向快洗之后那天建容量INF费用f的边,慢洗也是,注意要和下一天建边,容量INF费用0,因为可以不洗……所以还是要拆点,至于新买的,自然费用为price,容量inf,总结一下:

1、从source向每个xi连一条容量为ri,费用为0的有向边

2、从每个yi向sink连一条容量为ri,费用为0的有向边

3、从source向每个yi连一条容量为INF,费用为p的有向边

4、从每个xi向xi+1(i+1<=day)连一条容量为INF,费用为0的有向边(有餐巾会留到明天)

5、从每个xi向yi+m(i+m<=day)连一条容量为INF,费用为f的有向边

6、从每个xi向yi+n(i+n<=day)连一条容量为INF,费用为s的有向边

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <functional>#include <queue>using namespace std;int cnt=1,nd,price,m,f,n,s,ans;bool inq[2005];const int INF = 0x3f3f3f3f;const int MAXN = 80003;const int MAXE = 160003;struct Edge {    int from, to, nxt, cap, flow, cost;    Edge() {}    Edge(int from, int to, int nxt, int cap, int flow, int cost):from(from), to(to), nxt(nxt), cap(cap), flow(flow), cost(cost) {}}e[MAXE];int h[MAXN], p;int source, sink;int cur[MAXN];int d[MAXN];queue<int> q;bool exist[MAXN];inline void add_edge(int x, int y, int cap, int cost) {    e[p] = Edge(x, y, h[x], cap, 0, cost); h[x] = p++;    e[p] = Edge(y, x, h[y], 0, 0, -cost); h[y] = p++;}bool SPFA() {    memset(d, 0x3f, sizeof(d));    memset(exist, 0, sizeof(exist));    memset(cur, -1, sizeof(cur));    q.push(source);    d[source] = 0;    exist[source] = 1;    while(!q.empty()) {        int u = q.front(); q.pop();        exist[u] = 0;        for(int i = h[u]; ~i; i = e[i].nxt) {            int v = e[i].to;            if(e[i].cap > e[i].flow && d[v] > d[u] + e[i].cost) {                d[v] = d[u] + e[i].cost;                cur[v] = i;                if(!exist[v]) {                    q.push(v);                    exist[v] = 1;                }            }        }    }    return d[sink] != INF;}long long MCMF() {    long long cost = 0;    while(SPFA()) {        int flow = INF;        for(int i = sink; i != source; i = e[cur[i]].from) flow = min(flow, e[cur[i]].cap - e[cur[i]].flow);        for(int i = sink; i != source; i = e[cur[i]].from) {            e[cur[i]].flow += flow;            e[cur[i] ^ 1].flow -= flow;        }        cost += flow * d[sink];    }    return cost;}int main(){    memset(h, -1, sizeof(h));    scanf("%d", &nd);    int x;source = 0; sink = 8000;    for(int i = 1; i <= nd; i++)    {            scanf("%d",&x);            add_edge(source, i, x, 0);//连源点汇点            add_edge(nd + i, sink, x, 0);    }    scanf("%d%d%d%d%d", &price, &m, &f, &n, &s);    for(int i = 1; i <= nd; i++)    {        if(i + 1 <= nd)add_edge(i, i + 1, INF, 0);//留到明天        if(i + m <= nd)add_edge(i, nd + i + m, INF, f);//快洗        if(i + n <= nd)add_edge(i, nd + i + n, INF, s);//慢洗        add_edge(source, nd+i, INF, price);//新买    }    printf("%d\n",MCMF());    return 0;}



阅读全文
1 0