題面傳送機
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;
}