Codeforces 653D Delivery Bears【二分+网络流】
题目链接:
http://codeforces.com/problemset/problem/653/D
题意:
x个熊拿着相同重量的物品,从1号结点沿着路走到N号结点,结点之间有边相连,保证可以从1号走到N号。
The total weight that travels across a particular edge must not exceed the weight capacity of that edge.
所有经过这条边的熊,他们所拿的重量之和不能大于这条边的容量。
求所有熊所能拿的最大重量之和。
分析:
很明显的网络流。
理解了题意便可以想到直接二分每个熊可以拿的重量,每边的容量代表经过熊的个数,这样在每次judge的时候对边进行处理,判断是否满流就好啦~~~
代码:
#include<cstdio>
#include<iostream>
#include<queue>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
typedef pair<int, int>pii;
#define fi first
#define se second
struct edge{int to, cap, rev;};
const int maxn = 10005, maxm = 20100, INF = 0x3f3f3f3f;
int d[maxm], iter[maxm];
int s, t;
int x, m;
int n, q;
vector<edge>G[maxm];
pii u[maxn];
int a[maxn], b[maxn], c[maxn];
void add_edge(int from, int to, int cap)
{
G[from].push_back((edge){to, cap, G[to].size()});
G[to].push_back((edge){from, 0, G[from].size()-1});
}
void bfs()
{
memset(d, -1, sizeof(d));
queue<int>q;
d[s] = 0;
q.push(s);
while(!q.empty()){
int v = q.front();q.pop();
for(int i = 0; i <G[v].size(); i++){
edge &e = G[v][i];
if(e.cap>0&&d[e.to]<0){
d[e.to] = d[v] + 1;
q.push(e.to);
}
}
}
}
int dfs(int v, int f)
{
if(v == t) return f;
for(int &i = iter[v]; i < G[v].size(); i++){
edge &e = G[v][i];
if(e.cap > 0 && d[v] < d[e.to]){
int tf = dfs(e.to, min(f, e.cap));
if(tf > 0){
e.cap -= tf;
G[e.to][e.rev].cap +=tf;
return tf;
}
}
}
return 0;
}
int max_flow()
{
int flow = 0;
for(;;){
bfs();
if(d[t]<0) return flow;
memset(iter, 0, sizeof(iter));
int f;
while((f = dfs(s, INF))>0){
flow += f;
}
}
}
bool judge(double mid)
{
for(int i = 0; i < maxn; i++)
G[i].clear();
for(int i = 0; i < m; i++){
add_edge(a[i], b[i], min(1.0 * x, (double)c[i]/mid));//注意容量可能会爆int,所以取和x的最小值就好~
}
add_edge(n, t, x);
add_edge(s, 1, x);
return max_flow() == x;
}
int main (void)
{
scanf("%d%d%d",&n, &m, &x);
for (int i = 0; i < m; i++){
scanf("%d%d%d", &a[i], &b[i], &c[i]);
}
s = 0, t = n + 1;
add_edge(n, t, INF);
add_edge(s, 1, x);
double l = 0, r = 1000005;
for(int i = 0; i < 100; i++){
double mid = (l + r)/2;
if(judge(mid)) l = mid;
else r = mid;
}
printf("%.10f", l*x);
}