您的位置:首页 > 理论基础 > 计算机网络

IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2) 二分答案 + 网络流

2016-03-20 20:51 459 查看
  这道题的意思是给你一个有向图, 每条边上有一个最大载重量, 现在有x头牛要从顶点1走向顶点n, 每头牛要载的重量都是一样的, 问你最多能载多少的重量? 可以二分答案, 算出每头牛的载重, 然后修改边权, 跑一次最大流即可判断当前答案是否正确, 二分答案即可, 注意由于原始边权/每头牛的载重量可能会很大, 因此我们在修改边权时应该注意这一点,将边权的最大值控制在1000000之内, 防止溢出, 代码如下:

#include <bits/stdc++.h>

using namespace std;
const int maxn = 100;
int n, m, x;

struct Dinic{
int n;
struct edge {int from, to, cap;};
vector<int> G[maxn];
vector<edge> e;
int level[maxn], iter[maxn];
void init() {
for(int i=0; i<=n; i++) G[i].clear();
e.clear();
}
void add_edge(int u, int v, int cap){
e.push_back((edge){u, v, cap});
e.push_back((edge){v, u, 0});
int m = e.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}
void bfs(int s){
memset(level, -1, sizeof(level));
queue<int> que;
level[s] = 0;
que.push(s);
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i=0; i<G[u].size(); i++) {
edge &te = e[G[u][i]];
if(te.cap>0 && level[te.to]<0){
level[te.to] = level[u] + 1;
que.push(te.to);
}
}
}
}
int dfs(int v, int t, int f){
if(v == t) return f;
for(int &i=iter[v]; i<G[v].size(); i++){
edge &tpe = e[G[v][i]];
if(tpe.cap>0 && level[v]<level[tpe.to]){
int d = dfs(tpe.to, t, min(f, tpe.cap));
if(d > 0) {
tpe.cap -= d;
e[G[v][i]^1].cap += d;
return d;
}
}
}
return 0;
}
int max_flow(int s, int t){
int flow = 0;
for( ;; ){
bfs(s);
if(level[t]<0) return flow;
memset(iter, 0, sizeof(iter));
int f;
while((f=dfs(s, t, 0x3f3f3f3f)) > 0) flow += f;
}
}
}di, di2;

bool check(double mid) {
double eve = mid/(double)x;
di2 = di;
for(int i=0; i<di2.e.size(); i++) {
di2.e[i].cap = min((double)di2.e[i].cap/eve, (double)1000000+100);
}
//    printf(" ----------- \n");
//    for(int i=0; i<di2.e.size(); i++) {
//        if(di2.e[i].cap) printf("%d %d %d\n", di2.e[i].from, di2.e[i].to, di2.e[i].cap);
//    }
int res = di2.max_flow(1, n);
return res >= x;
}

int main() {
scanf("%d%d%d", &n, &m, &x);
di.n = n;
di.init();
for(int i=0; i<m; i++){
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
di.add_edge(u, v, c);
}
double l=0, r=(double)0x3f3f3f3f;
double res = 0;
for(int i=0; i<1000; i++) {
double mid = (l+r)/2;
if(check(mid)){
res = mid;
l = mid;
} else r = mid;
}
printf("%.10f\n", res);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: