( m Son ~of ~Pipe~ Stream(DJ))
给定一张 (n) 个点,(m) 条边的图,将这张图进行一次“复制”我们得到了两张完全相同的图,这两张图均以 (3) 号点作为汇点,但第一张图以 (1) 号节点作为源点,第二张图以第 (2) 号节点作为源点。
给定常数 (v,a),同时每条边有边权 (c_i)
现在,你需要给两张图上的每条边确定一个流量和方向,在两张图上一条边的方向应该是一致的,除源点和汇点每个点需满足流量平衡,同时对于每条边有约束:
- (vcdot f_i+w_ile c_i)
其中 (f_i) 为第一张图上此边的流量 (w_i) 为第二张图上此边的流量。
对于流入汇点的流量,设 (F) 为第一张图上流入汇点的流量,(W) 为第二张图上流入汇点的流量,你需要最大化 (F^acdot W^{1-a})
(nle 300,mle frac{n(n-1)}{2}),答案的绝对误差不应超过 (10^{-4})
Solution
考虑 (frac{v^aF^aW^{1-a}}{v^a}=frac{(vF)^aW^{1-a}}{v^a})
对于每条边,令 (f_i'=vcdot f_i),限制等价于 (f_i'+w_ile c_i)
考虑怎样的一组 (F,W) 是合法的,我们先跑出 (F) 的上界 (F_{max}),跑出 (W) 的上界 (W_{max}),然后跑出 (S=(F+W)_{max})
可以证明只要一组 ((F',W')) 满足此约束那么他都是合法的。
证明:
首先可以证明 ((F_{max},S-F_{max})) 是合法的,因为我们可以先流 (F_{max}),然后再将残余网络给第二部分流,因为不会退流给起始点,又因为我们任意增广总是可以流到最大流,所以 (S-F_{max}) 是一定可以取到的。
类似的,((S-W_{max},W_{max})) 也可以取到。
对于任意的 ((F',W')),我们考虑这两张图的流量网络,我们通过 (alpha) 和 (1-alpha) 总是能够组成 ((F',W')),所以最后的策略为先流 (alpha imes (F_{max},S-F_{max})+(1-alpha) imes (S-W_{max}, W_{max})),然后得到答案。
等一下,还有一个限制,两张图上的边必须同向。
可以这样考虑,我们先求出 (F') 和 (W') 然后跑一次最大流。
此时我们重构这张图,每条边的方向为此流的方向,每条边的容量为此流中的容量,然后再从 (1) 开始跑一次最大流,将边删掉,就是从 (2) 出发的流量了。
然后由于 (S) 确定,答案相当于 ((F+W)=S,F^aW^{1-a}) 的最大值,取在 (F'=acdot S) 处有最大值。
(Code:)
#include<bits/stdc++.h>
using namespace std ;
#define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
#define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
#define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
#define re register
#define mp make_pair
const double inf = 1e9 ;
const int N = 200 + 5 ;
const int M = 1e5 + 5 ;
int n, m, top ;
struct S { int x, y ; double z ; } s[M], st[M] ;
double K, alpha ;
map<pair<int, int>, int> sf ;
map<pair<int, int>, double> dw ;
map<pair<int, int>, double> cost, FF ;
struct Flow {
int S, T, cnt, dep[N], head[N], cur[N] ;
struct E {
int fr, to, next ; double w ;
} e[M] ;
void undir(int x, int y, double z) { //undircet
e[++ cnt] = (E){ x, y, head[x], z }, head[x] = cnt,
e[++ cnt] = (E){ y, x, head[y], z }, head[y] = cnt ;
}
void dir(int x, int y, double z) { //dircet
e[++ cnt] = (E){ x, y, head[x], z }, head[x] = cnt,
e[++ cnt] = (E){ y, x, head[y], 0 }, head[y] = cnt ;
}
queue<int> q ;
bool bfs() {
rep( i, 0, n ) dep[i] = 0 ; dep[S] = 1, q.push(S) ;
while( !q.empty() ) {
int u = q.front() ; q.pop() ;
Next( i, u ) {
int v = e[i].to ;
if( !dep[v] && e[i].w )
dep[v] = dep[u] + 1, q.push(v) ;
}
} return (dep[T] != 0);
}
double dfs(int x, double dist) {
if(x == T) return dist ; double flow = 0 ;
for(int &i = cur[x]; i; i = e[i].next) {
int v = e[i].to ;
if((dep[v] == dep[x] + 1) && e[i].w ){
double di = dfs(v, min(dist, e[i].w)) ;
e[i].w -= di, e[i ^ 1].w += di,
dist -= di, flow += di ;
if( !dist ) return flow ;
}
} return flow ;
}
double dinic() {
double ans = 0 ;
while(bfs()) {
memcpy(cur, head, sizeof(head)) ;
while(double di = dfs(S, inf)) ans += di ;
} return ans ;
}
void build() {
for(re int i = 2; i <= cnt; ++ i ) {
if( e[i].fr == 0 || e[i].to == 0 ) continue ;
double c = dw[mp(e[i].fr, e[i].to)] ;
if( c <= e[i].w ) continue ;
c -= e[i].w, ++ top ;
st[top].x = e[i].fr, st[top].y = e[i].to, st[top].z = c ;
cost[mp(e[i].fr, e[i].to)] = c ;
cost[mp(e[i].to, e[i].fr)] = - c ;
}
}
void put() {
for(re int i = 2; i <= cnt; i += 2) {
if( e[i].fr == 0 || e[i].to == 0 ) continue ;
double c = e[i ^ 1].w ;
FF[mp(e[i].fr, e[i].to)] = c ;
FF[mp(e[i].to, e[i].fr)] = -c ;
}
}
void init() {
S = 0, T = 3, cnt = 1, memset( head, 0, sizeof(head) ) ;
}
} flow[3] ;
signed main()
{
cin >> n >> m >> K >> alpha ;
rep( i, 0, 2 ) flow[i].init() ;
int x, y ; double z ;
rep( i, 1, m ) {
cin >> x >> y >> z, s[i] = (S){x, y, z} ;
sf[mp(x, y)] = 1, sf[mp(y, x)] = -1 ;
rep( j, 0, 2 ) flow[j].undir(x, y, z) ;
dw[mp(x, y)] = dw[mp(y, x)] = z ;
}
flow[0].S = 1, flow[1].S = 2, flow[2].S = 0 ;
flow[2].undir(0, 1, inf), flow[2].undir(0, 2, inf) ;
double F = flow[0].dinic() ;
double W = flow[1].dinic() ;
double Z = flow[2].dinic() ;
double ll = Z - W, rr = F ;
double ff = max(ll, min(rr, alpha * Z)) ;
double ans = pow(ff, alpha) * pow(Z - ff, 1 - alpha) ;
ans = ans / pow(K, alpha) ;
flow[2].init() ;
rep( i, 1, m )
x = s[i].x, y = s[i].y, z = s[i].z,
flow[2].undir(x, y, z) ;
flow[2].S = 0, flow[2].dir(0, 1, ff), flow[2].dir(0, 2, Z - ff) ;
flow[2].dinic(), flow[2].build(), flow[2].init() ;
rep( i, 1, top )
x = st[i].x, y = st[i].y, z = st[i].z, flow[2].dir(x, y, z) ;
flow[2].dir(0, 1, ff), flow[2].dinic(), flow[2].put() ;
rep( i, 1, m ) {
x = s[i].x, y = s[i].y ;
printf("%.10lf %.10lf
", FF[mp(x, y)] / K, cost[mp(x, y)] - FF[mp(x, y)] ) ;
}
printf("%.10lf
", ans ) ;
return 0 ;
}