将
c
i
c_i
ci 看作边
(
u
i
,
v
i
)
(u_i,v_i)
(ui,vi) 的流量,并将每条边的容量都看作
∞
∞
∞。
将
a
i
a_i
ai 看作把边
(
u
i
,
v
i
)
(u_i,v_i)
(ui,vi) 增广
1
1
1 单位流量的花费,
b
i
b_i
bi 看作将
(
u
i
,
v
i
)
(u_i,v_i)
(ui,vi) 退
1
1
1 单位流量的花费,也就是把边
(
v
i
,
u
i
)
(v_i,u_i)
(vi,ui) 增广
1
1
1 单位流量的花费。
将
d
i
d_i
di 看作把边
(
u
i
,
v
i
)
(u_i,v_i)
(ui,vi) 增广
1
1
1 单位流量的代价,同时也看作把边
(
v
i
,
u
i
)
(v_i,u_i)
(vi,ui) 增广
1
1
1 单位流量的收益。
令
r
e
s
=
X
−
Y
res=X-Y
res=X−Y,显然
⌊
\lfloor
⌊ 把
(
u
i
,
v
i
)
(u_i,v_i)
(ui,vi) 增广
1
1
1 单位流量
⌋
\rfloor
⌋ 对
r
e
s
res
res 的贡献是
−
b
i
−
d
i
-b_i-d_i
−bi−di,
⌊
\lfloor
⌊ 把
(
v
i
,
u
i
)
(v_i,u_i)
(vi,ui) 增广
1
1
1 单位流量
⌋
\rfloor
⌋ 对
r
e
s
res
res 的贡献是
d
i
−
a
i
d_i-a_i
di−ai。
注意
c
i
=
0
c_i=0
ci=0 时,不能增广
(
v
i
,
u
i
)
(v_i,u_i)
(vi,ui)。
先按上面所说的建好一张新图。
题目要求流量不能变少,又因为流量变多肯定不优,所以我们要让流量不变。
也就是说我们要增广一些环。
看到
(
X
−
Y
)
/
k
(X-Y)/k
(X−Y)/k,显然的分数规划模型。
二分答案,判断是否
r
e
s
/
k
≥
m
i
d
res/k≥mid
res/k≥mid,即是否
r
e
s
−
m
i
d
∗
k
≥
0
res-mid*k≥0
res−mid∗k≥0。
考虑将新图上的每条边减去
m
i
d
mid
mid,然后如果图上存在一个环使得边权和非负,那么
r
e
s
/
k
≥
m
i
d
res/k≥mid
res/k≥mid。
Code
#include<bits/stdc++.h>usingnamespace std;template<classt>inlinevoidread(t & res){char ch;while(ch =getchar(),!isdigit(ch));
res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+(ch ^48);}constint e =1e5+5;constdouble inf =1e18, eps =1e-4;int n, m, adj[e], nxt[e], go[e], num, s, cnt[e];double len[e], ans, dis[e];bool vis[e];inlinevoidadd(int x,int y,double v){
nxt[++num]= adj[x]; adj[x]= num; go[num]= y; len[num]= v;}inlineboolcheck(double mid){
queue<int>q;int i;for(i =1; i <= n +2; i++) vis[i]=1, dis[i]=0, cnt[i]=1, q.push(i);while(!q.empty()){int u = q.front();
q.pop();
vis[u]=0;for(i = adj[u]; i; i = nxt[i]){int v = go[i];if(dis[u]+ len[i]- mid >= dis[v]){
dis[v]= dis[u]+ len[i]- mid;
cnt[v]= cnt[u]+1;if(cnt[v]>= n +2)return1;if(!vis[v]) q.push(v), vis[v]=1;}}}return0;}intmain(){int i, u, v, ai, bi, ci, di;read(n);read(m); m--;while(m--){read(u);read(v);read(ai);read(bi);read(ci);read(di);add(u, v,-bi - di);if(ci)add(v, u, di - ai);}read(u);read(s);read(ai);read(bi);read(ci);read(di);double l =0, r =1e9;while(r - l > eps){double mid =(l + r)/2.0;if(check(mid)) ans = l = mid;else r = mid;}printf("%.2lf\n", ans);return0;}