洛谷2986
树状dp
d
p
[
i
]
dp[i]
d p [ i ] 以
i
i
i 为根时不方便程度
d
p
[
i
]
=
d
p
[
f
a
[
i
]
]
−
s
u
m
s
o
n
[
i
]
∗
w
(
i
,
f
a
[
i
]
)
+
(
n
−
s
u
m
s
o
n
[
i
]
)
∗
w
(
i
,
f
a
[
i
]
)
dp[i]=dp[fa[i]]-sumson[i]*w(i,fa[i]) + (n-sumson[i])*w(i,fa[i])
d p [ i ] = d p [ f a [ i ] ] − s u m s o n [ i ] ∗ w ( i , f a [ i ] ) + ( n − s u m s o n [ i ] ) ∗ w ( i , f a [ i ] )
s
u
m
s
o
n
[
i
]
sumson[i]
s u m s o n [ i ] 以
i
i
i 为根的子树所有结点奶牛总和,
n
n
n 所有结点奶牛总和爆搜求出
d
p
[
1
]
dp[1]
d p [ 1 ] ,跑树上dp 求出其余节点答案
LL dfs_1 ( int now, int fa)
{
sum_son[ now] = c[ now] ;
for ( int i= head[ now] ; i!= - 1 ; i= edge[ i] . next)
{
int v= edge[ i] . t;
if ( v!= fa)
sum_son[ now] += dfs_1 ( v, now) ;
}
return sum_son[ now] ;
}
void dfs_2 ( int now, int fa, LL w)
{
if ( now!= 1 )
dp[ 1 ] += w* c[ now] ;
for ( int i= head[ now] ; i!= - 1 ; i= edge[ i] . next)
{
int v= edge[ i] . t;
LL ww= edge[ i] . l;
if ( v!= fa)
{
dfs_2 ( v, now, w+ ww) ;
}
}
return ;
}
void dfs_3 ( int now, int fa, LL w)
{
if ( now!= 1 )
dp[ now] = dp[ fa] + ( sum_o- 2 * sum_son[ now] ) * ( w) ;
for ( int i= head[ now] ; i!= - 1 ; i= edge[ i] . next)
{
int v= edge[ i] . t;
LL ww= edge[ i] . l;
if ( v!= fa)
dfs_3 ( v, now, ww) ;
}
return ;
}
void solve ( )
{
LL ans= LINF;
memset ( head, - 1 , sizeof ( head) ) ;
for ( int i= 1 ; i< n; i++ )
add ( F[ i] , T[ i] , L[ i] ) , add ( T[ i] , F[ i] , L[ i] ) ;
for ( int i= 1 ; i<= n; i++ )
sum_o+= c[ i] ;
dfs_1 ( 1 , 1 ) ;
dfs_2 ( 1 , 1 , 0 ) ;
dfs_3 ( 1 , 1 , 0 ) ;
for ( int i= 1 ; i<= n; i++ )
ans= min ( ans, dp[ i] ) ;
cout<< ans<< endl;
return ;
}
洛谷2754
分层网络流 以时间分层
k
∗
(
n
+
2
)
+
i
k*(n+2)+i
k ∗ ( n + 2 ) + i ,
1
≤
i
≤
n
+
2
1 \leq i \leq n+2
1 ≤ i ≤ n + 2 分别为第k秒 的,地球,n个空间站,月球。 第
i
i
i 秒的地球和空间站分别向1秒后的自己建边容量无限,月球则反向建边 按飞船每秒所在位置建边容量为飞船容量 并查集检查是否有解 每秒一建边跑dinic最大流大于k即为最优解
struct node
{
int t, next;
LL l;
} edge[ N] ;
int tot, head[ N] , cur[ N] ;
int dep[ N] ;
int S, T;
void add ( int f, int t, LL l)
{
edge[ tot] . t= t;
edge[ tot] . l= l;
edge[ tot] . next= head[ f] ;
head[ f] = tot++ ;
}
bool bfs ( int now)
{
memset ( dep, 0 , sizeof ( dep) ) ;
dep[ now] = 1 ;
queue< int > Q;
Q. push ( now) ;
while ( ! Q. empty ( ) )
{
int u= Q. front ( ) ;
Q. pop ( ) ;
for ( int i= head[ u] ; i!= - 1 ; i= edge[ i] . next)
{
int v= edge[ i] . t;
if ( ! dep[ v] && edge[ i] . l)
{
dep[ v] = dep[ u] + 1 ;
Q. push ( v) ;
if ( v== T)
return true ;
}
}
}
return dep[ T] != 0 ;
}
LL dfs ( int now, LL flo)
{
LL lop= flo;
if ( now== T)
return flo;
for ( int i= cur[ now] ; i!= - 1 ; i= edge[ i] . next)
{
cur[ now] = edge[ i] . next;
int v= edge[ i] . t;
if ( dep[ v] == dep[ now] + 1 && edge[ i] . l)
{
LL p= dfs ( v, min ( lop, edge[ i] . l) ) ;
lop-= p;
edge[ i] . l-= p;
edge[ i^ 1 ] . l+= p;
if ( ! p)
dep[ v] = 0 ;
if ( ! lop)
break ;
}
}
return flo- lop;
}
int n, m, k;
int h[ 210 ] , r[ 210 ] , SS[ 210 ] [ 210 ] ;
int fa[ N] ;
int fin ( int x)
{
if ( fa[ x] == x)
return x;
return fa[ x] = fin ( fa[ x] ) ;
}
void solve ( )
{
LL ans= 0 ;
S= 0 , T= 1000000 ;
memset ( head, - 1 , sizeof ( head) ) ;
for ( int i= 1 ; i<= n+ 2 ; i++ )
fa[ i] = i;
for ( int i= 1 ; i<= m; i++ )
{
for ( int j= 2 ; j<= r[ i] ; j++ )
{
int x= SS[ i] [ j] , y= SS[ i] [ j- 1 ] ;
x= fin ( x) , y= fin ( y) ;
fa[ x] = y;
}
}
if ( fin ( 1 ) != fin ( n+ 2 ) )
{
cout<< "0" << endl;
return ;
}
add ( n+ 2 , T, INF) , add ( T, n+ 2 , 0 ) ;
for ( int i= 1 ; i<= 1000000 ; i++ )
{
add ( S, 1 + ( i- 1 ) * ( n+ 2 ) , INF) , add ( 1 + ( i- 1 ) * ( n+ 2 ) , S, 0 ) ;
for ( int j= 1 ; j<= n+ 1 ; j++ )
add ( j+ ( i- 1 ) * ( n+ 2 ) , j+ i* ( n+ 2 ) , INF) , add ( j+ i* ( n+ 2 ) , j+ ( i- 1 ) * ( n+ 2 ) , 0 ) ;
add ( n+ 2 + i* ( n+ 2 ) , n+ 2 + ( i- 1 ) * ( n+ 2 ) , INF) , add ( n+ 2 + ( i- 1 ) * ( n+ 2 ) , n+ 2 + i* ( n+ 2 ) , 0 ) ;
for ( int j= 1 ; j<= m; j++ )
{
int last= ( i) % r[ j] ;
if ( last== 0 )
last= r[ j] ;
last= SS[ j] [ last] ;
last+= ( i- 1 ) * ( n+ 2 ) ;
int now= ( i+ 1 ) % r[ j] ;
if ( now== 0 )
now= r[ j] ;
now= SS[ j] [ now] ;
now+= i* ( n+ 2 ) ;
add ( last, now, h[ j] ) , add ( now, last, 0 ) ;
}
while ( bfs ( S) )
{
memcpy ( cur, head, sizeof ( head) ) ;
ans+= dfs ( S, INF) ;
}
if ( ans>= k)
{
cout<< i<< endl;
break ;
}
}
return ;
}
int main ( )
{
ios:: sync_with_stdio ( 0 ) ;
cin. tie ( 0 ) ;
cout. tie ( 0 ) ;
cin>> n>> m>> k;
for ( int i= 1 ; i<= m; i++ )
{
cin>> h[ i] >> r[ i] ;
for ( int j= 1 ; j<= r[ i] ; j++ )
{
cin>> SS[ i] [ j] ;
if ( SS[ i] [ j] != - 1 ) SS[ i] [ j] ++ ;
else SS[ i] [ j] = n+ 2 ;
}
}
solve ( ) ;
return 0 ;
}