poweroj1745: 餐巾计划问题

传送门 

最小费用最大流。

每天拆成两个点,i表示用完的餐巾,i+n表示干净的餐巾。

s向i连容量为ri费用为0的边,表示每天用脏的ri条餐巾。

i+n向t连容量为ri费用为0的边,表示每天需要用ri条餐巾。

s向1+n连容量为inf费用为p的边,表示新买进的干净餐巾,需要新买的在第一天全买了。

两种洗法都是,i 向 i+time+n 连容量为xx,费用为cost的边,表示第i天用完就洗干净放在洗完的第一天看哪天要用。

i+n向i+1+n连容量为Inf,费用为0的边,表示前一天没用的(新买的/洗干净的)干净餐巾,免费留到下一天用。

不明白为什么其他人都要把脏的留到什么时候需要再洗,不应该立刻洗了屯着么。。

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
const int N=1e6+7,inf=0x7fffffff;
typedef long long LL;
using namespace std;
int n,pp,kt,kv,mt,mv;

template<typename T> void read(T &x) {
    T f=1; x=0; char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

struct edge {
    int u,v,fl,cap,cost,nx;
    edge(){}
    edge(int u,int v,int fl,int cap,int cost,int nx):u(u),v(v),fl(fl),cap(cap),cost(cost),nx(nx){} 
}e[N]; 

int fir[N],ecnt=1;
void add(int u,int v,int cap,int cost) {
    e[++ecnt]=edge(u,v,0,cap,cost,fir[u]); fir[u]=ecnt;
    e[++ecnt]=edge(v,u,0,0,-cost,fir[v]); fir[v]=ecnt;
}

int vis[N],dis[N],p[N],tot;
queue<int>que;
int spfa(int s,int t) {
    for(int i=1;i<=tot;i++) vis[i]=0,dis[i]=inf;
    que.push(s); dis[s]=0;
    while(!que.empty()) {
        int x=que.front();
        que.pop(); vis[x]=0;
        for(int i=fir[x];i;i=e[i].nx) 
        if(e[i].cap>e[i].fl) {
            int y=e[i].v;
            if(dis[y]>dis[x]+e[i].cost) {
                dis[y]=dis[x]+e[i].cost;
                p[y]=i; 
                if(!vis[y]) {
                    vis[y]=1;
                    que.push(y);
                }
            }
        }
    }
    return dis[t]!=inf;
}

int calc(int s,int t) {
    int fl=inf,res=0;
    for(int i=t;i!=s;i=e[p[i]].u) 
        fl=min(fl,e[p[i]].cap-e[p[i]].fl),
        res+=e[p[i]].cost;
    for(int i=t;i!=s;i=e[p[i]].u) 
        e[p[i]].fl+=fl,e[p[i]^1].fl-=fl;
    return fl*res;
} 

int max_flow(int s,int t) {
    int res=0;
    while(spfa(s,t)) 
        res+=calc(s,t);
    return res;
}

int main() {
    read(n); read(pp); read(kt);
    read(kv); read(mt); read(mv);
    int s=n*2+1,t=s+1; tot=t;
    add(s,1+n,inf,pp);
    for(int i=1;i<=n;i++) {
        int xx; read(xx);
        add(s,i,xx,0);
        add(i+n,t,xx,0);
        if(i+1<=n) add(i+n,i+n+1,inf,0);
        if(i+kt<=n) add(i,i+n+kt,xx,kv);
        if(i+mt<=n) add(i,i+n+mt,xx,mv);
    }
    int ans=max_flow(s,t);
    printf("%d\n",ans);
    return 0;
}
View Code

 

posted @ 2018-01-29 19:12  啊宸  阅读(166)  评论(0编辑  收藏  举报