洛谷 3305.「SDOI2013」费用流

过分显然的是,Bob 一定是把 \(P\) 全都分配在流量最大的那条边上……

也就是在保证最大流的前提下,要流量最大的边的流量最小……
二分一下答案(需要实数),与原来的容量取个 min 跑最大流。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100;
const int M = 1e3;
const double eps = 1e-5;
int n,m,p,s,t;
struct Edge
{
int u,v,w;
} e[M + 5];
int to[(M << 1) + 5],pre[(M << 1) + 5],first[N + 5],cur[N + 5],edge_tot;
double val[(M << 1) + 5];
inline void add(int u,int v,double w)
{
int &tot = edge_tot;
to[tot] = v,val[tot] = w,pre[tot] = first[u],first[u] = tot++;
}
int head,tail,q[N + 5],dep[N + 5],vis[N + 5];
int bfs()
{
head = tail = 0;
memset(vis,0,sizeof vis);
memset(dep,0x3f,sizeof dep);
dep[s] = 0,vis[s] = 1,q[++tail] = s;
for(register int p;head < tail;)
{
vis[p = q[++head]] = 0;
for(register int i = first[p];~i;i = pre[i])
if(val[i] && dep[to[i]] > dep[p] + 1)
{
dep[to[i]] = dep[p] + 1;
if(!vis[to[i]])
vis[to[i]] = 1,q[++tail] = to[i];
}
}
return dep[t] ^ 0x3f3f3f3f;
}
double dfs(int p,double flow)
{
if(p == t)
return flow;
double ret = 0,used = 0;
for(register int i = cur[p];~i;cur[p] = i = pre[i])
if(val[i] > 0 && dep[to[i]] == dep[p] + 1 && (ret = dfs(to[i],min(flow - used,val[i]))) > 0)
{
used += ret,val[i] -= ret,val[i ^ 1] += ret;
if(used >= flow)
break;
}
return used;
}
double dinic()
{
double ret = 0;
while(bfs())
{
for(register int i = 1;i <= n;++i)
cur[i] = first[i];
ret += dfs(s,0x3f3f3f3f);
}
return ret;
}
int maxflow;
double l,r,mid,ans;
int check()
{
memset(first,-1,sizeof first),edge_tot = 0;
for(register int i = 1;i <= m;++i)
add(e[i].u,e[i].v,min((double)e[i].w,mid)),add(e[i].v,e[i].u,0);
double flow = dinic();
return fabs(flow - maxflow) < eps;
}
int main()
{
memset(first,-1,sizeof first);
scanf("%d%d%d",&n,&m,&p),s = 1,t = n;
for(register int i = 1;i <= m;++i)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w),add(e[i].u,e[i].v,e[i].w),add(e[i].v,e[i].u,0);
r = maxflow = dinic();
for(register int i = 1;i <= 100;++i)
mid = (l + r) / 2,check() ? (ans = r = mid) : (l = mid);
printf("%d\n%.4f\n",maxflow,ans * p);
}