大家都很强, 可与之共勉 。
惊了,我以前朱刘算法的模板是错的!!!!
题意:
您要买
n
种商品,每一种商品都有价格和需求量,有
题解:
坠小树形图,先跑出坠小树形图。确定每个东西买一个的最小总花费,然后所有东西一定可以以最小单价买到,累加就好了。
板子不对TTTTTTTTTTTTTTTLE
双倍经验题 BZOJ4349
/**************************************************************
Problem: 2260
User: Lazer2001
Language: C++
Result: Accepted
Time:16 ms
Memory:7932 kb
****************************************************************/
# include <bits/stdc++.h>
const int N = 100010 ;
class DMST {
private :
double in [N] ;
int id [N], pre [N], vis [N] ;
struct edge {
int u, v ; double c ;
} g [N << 1] ;
int ecnt ;
inline double Zhuliu_algorithm ( int root, int n ) {
double rt ( 0 ) ;
register int i, u, v ;
for ( ; ; ) {
for ( i = 1 ; i <= n ; ++ i ) in [i] = 1e10 ;
for ( i = 1 ; i <= ecnt ; ++ i ) {
u = g [i].u, v = g [i].v ;
if ( g [i].c < in [v] && ( u ^ v ) ) {
in [v] = g [i].c ;
pre [v] = u ;
}
}
for ( i = 1 ; i <= n ; ++ i ) {
if ( i != root && in [i] == 1e10 ) return -1 ;
}
int cnt ( 1 ) ;
memset ( id, -1, sizeof ( int ) * ( n + 1 ) ) ;
memset ( vis, -1, sizeof ( int ) * ( n + 1 ) ) ;
in [root] = 0 ;
for ( i = 1 ; i <= n ; ++ i ) {
rt += in [i] ;
int v = i ;
while ( vis [v] != i && id [v] == -1 && v != root ) {
vis [v] = i ;
v = pre [v] ;
}
if ( v != root && id [v] == -1 ) {
for ( u = pre [v] ; u != v; u = pre [u] )
id [u] = cnt ;
id [v] = cnt ++ ;
}
}
if ( cnt == 1 ) return rt ; //break ;
for ( i = 1 ; i <= n ; ++ i ) if ( id [i] == -1 ) id [i] = cnt ++ ;
for ( i = 1 ; i <= ecnt ; ++ i ) {
v = g [i].v ;
g [i].v = id [g [i].v] ;
g [i].u = id [g [i].u] ;
if ( g [i].u ^ g [i].v ) {
g [i].c -= in [v] ;
}
}
n = cnt - 1 ;
root = id [root] ;
}
// return rt ;
}
public :
DMST ( ) { ecnt = 0 ; }
inline void add_edge ( int u, int v, double w ) {
g [++ ecnt] = ( edge ) { u, v, w } ;
}
inline double main ( int root, int n ) {
return Zhuliu_algorithm ( root, n ) ;
}
} T ;
double c [N] ;
int need [N] ;
int id [N] ;
int main ( ) {
int n ;
scanf ( "%d", & n ) ;
int cnt ( 0 ) ;
for ( int i = 1 ; i <= n ; ++ i ) {
scanf ( "%lf%d", c + i, need + i ) ;
if ( need [i] ) id [i] = ++ cnt ;
}
int root = cnt + 1 ; // cnt ;
for ( int i = 1 ; i <= n ; ++ i ) if ( id [i] ) T.add_edge ( root, id [i], c [i] ) ; // c [i]...
int k ;
scanf ( "%d", & k ) ;
while ( k -- ) {
int u, v ; double cost ;
scanf ( "%d%d%lf", & u, & v, & cost ) ;
if ( ( ! id [u] ) || ( ! id [v] ) ) continue ;
if ( cost < c [v] ) c [v] = cost ;
T.add_edge ( id [u], id [v], cost ) ;
}
double ans = T.main ( root, cnt + 1 ) ;
for ( int i = 1 ; i <= n ; ++ i )
if ( need [i] > 1 ) {
ans += 1.0 * ( need [i] - 1 ) * c [i] ;
}
printf ( "%.2lf\n", ans ) ;
return 0 ;
}