[網絡流24題10] 餐巾計劃問題

題面傳送機

Sol

最小費用最大流
建圖方式真麻煩 真是網絡流裏的泥石流清流啊
老規矩 先建立超源點S和超匯點E
對於每一天 , 我們可以拆成2個點 , 一個點稱爲1號連接S , 另外一個稱爲2號連接E , 流量都是當天餐巾 , 費用0
由於我們可以不洗餐巾所以可以直接連接下一天 (倆一號點連接), 費用爲0 , 流量INF(注意邊界)
我們可以買餐巾所以可以直接買直接S連向2號點 流量爲INF 費用爲價格
還可以洗餐布 , 把每天與洗完之後(i + n + day)的那一天的二號點相連 費用爲洗餐布費用 流量INF(注意邊界)

Code

#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstring>
typedef int trueint;
#define int long long
#define inc(i) (i = -(~i))
#define dec(i) (i = ~(-i))
using namespace std;

namespace fast
{
    inline char Getchar()
    {
        static char buf[1000001] , *p1 = buf , *p2 = buf;
        return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 1000000 , stdin) , p1 == p2) ? EOF : *p1 ++;
    }
    inline int read()
    {
        int num = 0; char c = 0;
        while(!isdigit(c)) c = Getchar();
        while(isdigit(c)) num = num * 10 + c - '0' , c = Getchar();
        return num;
    }
}
using namespace fast;

const int N = 20000 + 7 , M = 2000000 + 7 , INF = 0x3f3f3f3f;
int n , Fast_Wash_Cost , Fast_Wash_Day , Slow_Wash_Cost , Slow_Wash_Day , Everyday[N] , Buy;//in
int Head[N] , Node[M] , W[M] , Next[M] , tot = 1 , S , E , Co[M];//Map
int Min_Cost , Dep[N];//Others

inline void Add(int u , int v , int Flow , int Cost)
{
    Next[inc(tot)] = Head[u] , Head[u] = tot , W[tot] = Flow , Node[tot] = v , Co[tot] = Cost;
    Next[inc(tot)] = Head[v] , Head[v] = tot , W[tot] = 0 , Node[tot] = u , Co[tot] = -Cost;
}

inline void Build_Map()
{
    for(int i = 1 ; i <= n ; inc(i))
    {
        Add(S , i , Everyday[i] , 0);//拆點1號連起點
        Add(i + n , E , Everyday[i] , 0);//拆點2號連終點
        Add(S , i + n , INF , Buy);//買新的
        if(i < n)   Add(i , i + 1 , INF , 0);
        if(i + Fast_Wash_Day <= n)   Add(i , i + Fast_Wash_Day + n , INF , Fast_Wash_Cost);
        if(i + Slow_Wash_Day <= n)   Add(i , i + Slow_Wash_Day + n , INF , Slow_Wash_Cost);
    }
}

struct Queue
{
    int Que[N] , l , r;
    inline void cls() {l = 100 , r = 99;}
    inline int top() {return Que[l];}
    inline void push(int x) {Que[inc(r)] = x;}
    inline bool full() {return r >= l;}
    inline void pop() {inc(l);}
}Q;

bool inq[N] , book[N];
inline bool SPFA()
{
    memset(inq , 0 , sizeof(inq));
    memset(Dep , 0x3f3f3f3f , sizeof(Dep));
    int Big = Dep[1] , u , v;
    Q.cls() , Dep[S] = 0 , Q.push(S);
    while(Q.full())
    {
        u = Q.top() , Q.pop() , inq[u] = 0;
        for(int i = Head[u] ; i ; i = Next[i])
        {
            v = Node[i];
            if(Dep[v] > Dep[u] + Co[i] && W[i])
            {
                Dep[v] = Dep[u] + Co[i];
                if(!inq[v])
                {
                    inq[v] = 1;
                    Q.push(v);
                }
            }
        }
    }
  // printf("Dep[E] = %lld\n" , Dep[E]);
    return Dep[E] != Big;
}

inline int DFS(int u , int lastc)
{
    if(u == E) return lastc;
    int Now = 0 , v , Flow;
    book[u] = 1;
    for(int i = Head[u] ; i ; i = Next[i])
    {
        v = Node[i];
        if(W[i] && !book[v] && Dep[u] == Dep[v] - Co[i])
        {
            Flow = DFS(v , min(lastc - Now , W[i]));
            if(Flow)
            {
                W[i] -= Flow;
                W[i ^ 1] += Flow;
                Now += Flow;
                Min_Cost += Flow * Co[i];
                if(Now == lastc)    break;
            }
        }
    }
   // printf("Now = %lld\n" , Now);
    return Now;
}

inline void Max_Flow()
{
    int Flow;
    while(SPFA())
    {
        // printf("RE1");
        while(1)
        {
            // printf("RE2");
            memset(book , 0 , sizeof(book));
            Flow = DFS(S , INF);
            if(!Flow)   break;
        }
    }
}

trueint main()
{
    n = read();
    for(int i = 1 ; i <= n ; inc(i))    Everyday[i] = read();
    S = n + n + n + 2 , E = S + 2;
    Buy = read() , Fast_Wash_Day = read() , Fast_Wash_Cost = read() , Slow_Wash_Day = read() , Slow_Wash_Cost = read();
    Build_Map();
    Max_Flow();
    printf("%lld" , Min_Cost);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章