1. 程式人生 > >P1251 餐巾計劃問題 網路流之最小費用流

P1251 餐巾計劃問題 網路流之最小費用流

P1251 因為是一天中有不同的事務,現將一天拆點為晚上i 和早上i+N。 流向i的流是髒毛巾,流向早上的為乾淨毛巾。 建圖: 設一源點s,匯點t。

  1. s - > i 流量x,花費0. 表示到晚上有x條髒毛巾產生。
  2. i + N -> t ,流量 x , 花費0 .表示每天早上向匯點提供x條幹淨毛巾,如果滿流,則此天的毛巾夠用。
  3. i -> i + 1 . 流量INF , 花費0 。表示第i天晚上的髒毛巾可以不洗,留到i+1天晚上。
  4. i -> i + N + m . 流量INF ,花費fs 。表示第i天晚上的髒毛巾可以送去快洗,到i+m天早上可以用。
  5. i -> i + N + n . 流量INF,花費sl。表示第i天晚上的髒毛巾可以送去慢西,到弟i+n天早上可以用。
  6. s -> i + N ,流量INF,花費p。表示早上可以購買毛巾。 Code:
#include <bits/stdc++.h>
#define LL long long 
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 5e4 + 666 ;
struct Node{
	int u , v , next1 , flow , cost  ;
	Node( int u = 0 , int v = 0 , int flow = 0 , int cost = 0 , int next1 = 0 ):u(u),v(v),flow
(flow),cost(cost),next1(next1){} }G[AX*10]; int head[AX]; LL dis[AX] ; int pre[AX] ; int idx[AX*10] ; int fl[AX] ; int tot ; int s, t ; bool vis[AX] ; void addEdge( int u , int v , int w , int c ){ G[tot] = Node( u , v , w , c , head[u] ) ; head[u] = tot ++ ; G[tot] = Node( v , u , 0 , -c, head[
v] ) ; head[v] = tot ++ ; } int SPFA( ){ memset( dis , INF , sizeof(dis) ) ; memset( fl , INF , sizeof(fl) ) ; memset( vis , false , sizeof(vis) ) ; queue<int>q ; q.push(s) ; dis[s] = 0 ; pre[t] = 0 ; while( !q.empty() ) { int u = q.front(); q.pop() ; vis[u] = false; for( int i = head[u] ; ~i ; i = G[i].next1 ) { int v = G[i].v ; if( G[i].flow && dis[u] + G[i].cost < dis[v] ){ dis[v] = dis[u] + G[i].cost ; pre[v] = u ; idx[v] = i ; fl[v] = min( fl[u] , G[i].flow ) ; if( !vis[v] ){ vis[v] = true ; q.push(v) ; } } } }return pre[t] ; } int main(){ int N ; tot = 0 ; memset( head , -1, sizeof(head) ) ; scanf("%d",&N) ; int x ; s = 0 ; t = 2 * N + 1 ; for( int i = 1 ; i <= N ; i++ ){ scanf("%d",&x); addEdge( s , i , x , 0 ) ; addEdge( i + N , t , x , 0 ) ; } int p , m , fs , n , sl ; scanf("%d%d%d%d%d",&p,&m,&fs,&n,&sl); for( int i = 1 ; i <= N ; i++ ){ if( i + 1 <= N ) addEdge( i , i + 1 , INF , 0 ) ; if( i + m <= N ) addEdge( i , i + m + N , INF , fs ) ; if( i + n <= N ) addEdge( i , i + n + N , INF , sl ) ; addEdge( s , i + N , INF , p ) ; } LL rs_cost = 0 ; while( SPFA() ){ rs_cost += 1LL* fl[t] * dis[t] ; for( int i = t ; i != s ; i = pre[i] ){ G[idx[i]].flow -= fl[t] ; G[idx[i]^1].flow += fl[t] ; } } printf("%lld\n",rs_cost); return 0 ; }