题目链接
题目大意:
解题思路:
有源汇上下界最小费用可行流模板题目来着 先建出一个有源汇上下界可行流的图,然后注意建图的时候要把每条边的下界的费用提前加到ans里面 然后再对图跑费用流,就是补齐费用
AC code
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 4010 ;
const ll INF = 0x3f3f3f3f3f3f3f3f ;
int n, m;
struct node {
int nxt, to;
ll flow, w;
} edge[ maxn * 10 ] ;
int head[ maxn] , cnt;
inline void add ( int from, int to, int flow, int cost) {
edge[ cnt] = { head[ from] , to, flow, cost} ;
head[ from] = cnt ++ ;
edge[ cnt] = { head[ to] , from, 0 , - cost} ;
head[ to] = cnt ++ ;
}
ll dis[ maxn] , incf[ maxn] ;
int vis[ maxn] , pre[ maxn] ;
int s, t;
inline bool spfa ( ) {
queue< int > q;
memset ( dis, INF, sizeof ( dis) ) ;
memset ( vis, 0 , sizeof ( vis) ) ;
q. push ( s) ;
dis[ s] = 0 ;
vis[ s] = 1 ;
incf[ s] = 1 << 30 ;
while ( ! q. empty ( ) ) {
int u = q. front ( ) ;
vis[ u] = 0 ;
q. pop ( ) ;
for ( int i = head[ u] ; ~ i; i = edge[ i] . nxt) {
if ( ! edge[ i] . flow) continue ;
int v = edge[ i] . to;
if ( dis[ v] > dis[ u] + edge[ i] . w) {
dis[ v] = dis[ u] + edge[ i] . w;
incf[ v] = min ( incf[ u] , edge[ i] . flow) ;
pre[ v] = i;
if ( ! vis[ v] ) vis[ v] = 1 , q. push ( v) ;
}
}
}
return dis[ t] != INF;
}
ll ans;
inline void MCMF ( ) {
ll mincost = 0 ;
while ( spfa ( ) ) {
int x = t;
mincost += dis[ x] * incf[ x] ;
int i;
while ( x != s) {
i = pre[ x] ;
edge[ i] . flow -= incf[ t] ;
edge[ i^ 1 ] . flow += incf[ t] ;
x = edge[ i^ 1 ] . to;
}
}
ans += mincost;
}
inline void init ( ) {
memset ( pre, 0 , sizeof ( pre) ) ;
memset ( incf, INF, sizeof ( incf) ) ;
memset ( head, - 1 , sizeof ( head) ) ;
cnt = 0 ;
}
int in[ maxn] , out[ maxn] ;
int main ( ) {
ios:: sync_with_stdio ( 0 ) ;
cin. tie ( 0 ) ;
cout. tie ( 0 ) ;
init ( ) ;
int n;
cin >> n;
int s1 = 1 , t1 = n + 1 , s2 = n+ 2 , t2 = n + 3 ;
for ( int i = 1 ; i <= n; ++ i) {
int ki;
cin >> ki;
for ( int j = 1 ; j <= ki; ++ j) {
int v, w;
cin >> v >> w;
in[ v] ++ ;
out[ i] ++ ;
ans += 1 * w;
add ( i, v, INF- 1 , w) ;
}
}
for ( int i = 2 ; i <= n; ++ i)
add ( i, t1, INF, 0 ) ;
for ( int i = 1 ; i <= n; ++ i)
if ( in[ i] > out[ i] )
add ( s2, i, in[ i] - out[ i] , 0 ) ;
else if ( in[ i] < out[ i] )
add ( i, t2, out[ i] - in[ i] , 0 ) ;
add ( t1, s1, INF, 0 ) ;
s = s2, t = t2;
MCMF ( ) ;
cout << ans;
return 0 ;
}