题目
思路
贪心地看,我们直接把所有p都给到容量用的最多的边,然后我们的目的就是找到一个最大流中流量最多的边的最小值,可以考虑二分这个值,然后给每个点限流,重新建边时把初始的流量和二分的这个值去最小值,然后重新算一遍最大流。对于重边,不能将他们合并,而要算作不同的边,否则会影响最大流的值。
使用弧优化的dinic,没有弧优化会TLE。时间复杂度 O ( n 2 log m ) O(n^2\log m) O(n2logm)。
Code
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ESP 1e-8
#define DB double
#define MAXN 20005
#define MAXM 200005
#define Zhuan 10000
#define LL long long
#define Int register long long
#define MinINF 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
DB f[MAXN], p;
LL u[MAXN], v[MAXN], flow[MAXN];
LL n, m, cnt = -1, head[MAXN];
struct edge
{
DB f;
LL nxt, to;
}e[MAXM];
DB Abs(DB x)
{
if (x > 0)
return x;
return -x;
}
void add_edge(LL from,LL to,DB flw)
{
cnt ++;
e[cnt].nxt = head[from];
e[cnt].to = to;
e[cnt].f = flw;
head[from] = cnt;
}
void add_len(LL u,LL v,DB f)
{
add_edge(u, v, f);
add_edge(v, u, 0);
}
LL cur[MAXN], deep[MAXN];
bool bfs(int s, int t)
{
memcpy(cur, head, sizeof head);
memset(deep, 0x3f, sizeof deep);
queue<LL> Q;
deep[s] = 0; Q.push( s );
while (! Q.empty ())
{
LL u = Q.front(); Q.pop();
for (Int i = head[u]; ~ i; i = e[i].nxt)
{
LL v = e[i].to;
if (deep[v] == INF && Abs(e[i].f) > ESP)
{
deep[v] = deep[u] + 1;
Q.push( v );
}
}
}
return deep[t] != INF;
}
DB dfs (LL u,LL t,DB lim)
{
if (u == t || Abs(lim) < ESP)
return lim;
DB tmp = 0, flow = 0;
for (Int &i = cur[u]; ~ i; i = e[i].nxt)
{
LL v = e[i].to;
if (deep[v] == deep[u] + 1)
{
tmp = dfs(v, t, min(lim, e[i].f));
lim -= tmp;
flow += tmp;
e[i ^ 0].f -= tmp;
e[i ^ 1].f += tmp;
if (Abs(lim) < ESP)
break;
}
}
return flow;
}
DB Dinic (LL s,LL t)
{
DB Res = 0;
while (bfs(s, t))
Res += dfs(s, t, INF);
return Res;
}
DB MaxFlow;
bool Get(DB flw)
{
cnt = -1;
LL s = 1, t = n;
memset(head, -1, sizeof (head));
for (Int i = 1; i <= m; ++ i)
add_len(u[i], v[i], min(f[i], flw));
DB c = Dinic(s, t);
//printf("%lf %lf\n", c, flw);
return Abs(c - MaxFlow) < ESP;
}
int main()
{
memset(head, -1, sizeof (head));
cin >> n >> m >> p;
for (Int i = 1; i <= m; ++ i)
{
cin >> u[i] >> v[i] >> f[i];
add_len(u[i], v[i], f[i]);
}
LL s = 1, t = n;
MaxFlow = Dinic (s, t);
printf ("%.0lf\n", MaxFlow);
DB l = 0, r = MinINF;
while (l + ESP < r)
{
//printf("%lf %lf\n", l, r);
DB Mid = (l + r) / 2;
if (Get( Mid ))
r = Mid;
else l = Mid;
}
printf ("%.4lf\n", r * p);
return 0;
}