洛谷P4016 負載平衡問題 網路流之最大流最小費用流
阿新 • • 發佈:2018-12-17
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 ;
}