1. 程式人生 > >洛谷P4016 負載平衡問題 網路流之最大流最小費用流

洛谷P4016 負載平衡問題 網路流之最大流最小費用流

P4016 思路: 因為是每個倉庫貨物相等,那麼最後肯定是總和/個數(平均值ave)。 建圖: 源點s,匯點t。 如果i倉庫貨物大於平均值,那麼表示需要流出,所以: i -> t 流量為a[i] - ave , 花費0(必須輸出的流). 如果i倉庫貨物小於平均值,那麼表示需要匯入,所以: s-> i流量ave-a[i] , 花費0(必須得到的流). 另外,相鄰倉庫可以相互運輸. 建邊 i -> i + 1 , i - 1 - > i 流量INF,花費1. 環形注意處理。 Code:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std; const int AX = 1e3 + 6 ; int a[AX] ; struct Node{ int u , v , flow , cost , next1 ; 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]; int 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) ; s = n + 1 ; t = n + 2 ; int sum = 0 ; for( int i = 1 ; i <= n ; i++ ){ scanf("%d",&a[i]); sum += a[i] ; } sum /= n ; for( int i = 1 ; i <= n ; i++ ){ if( a[i] < sum ){ addEdge( s , i , sum - a[i] , 0 ) ; } if( a[i] > sum ){ addEdge( i , t , a[i] - sum , 0 ) ; } } for( int i = 1 ; i <= n ; i++ ){ int l = i - 1 ; int r = i + 1 ; if( l == 0 ) l = n ; if( r == n + 1 ) r = 1 ; addEdge( l , i , INF , 1 ) ; addEdge( i , l , INF , 1 ) ; addEdge( i , r , INF , 1 ) ; addEdge( r , i , INF , 1 ) ; } int rs_cost = 0 ; while( SPFA() ){ rs_cost += 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("%d\n",rs_cost); return 0 ; }