• BZOJ3130 [Sdoi2013]费用流 【网络流 + 二分】


    题目

    Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识。
    最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量。一个合法的网络流方案必须满足:(1)每条边的实际流量都不超过其最大流量且非负;(2)除了源点S和汇点T之外,对于其余所有点,都满足该点总流入流量等于该点总流出流量;而S点的净流出流量等于T点的净流入流量,这个值也即该网络流方案的总运输量。最大流问题就是对于给定的运输网络,求总运输量最大的网络流方案。

    上图表示了一个最大流问题。对于每条边,右边的数代表该边的最大流量,左边的数代表在最优解中,该边的实际流量。需要注意到,一个最大流问题的解可能不是唯一的。 对于一张给定的运输网络,Alice先确定一个最大流,如果有多种解,Alice可以任选一种;之后Bob在每条边上分配单位花费(单位花费必须是非负实数),要求所有边的单位花费之和等于P。总费用等于每一条边的实际流量乘以该边的单位花费。需要注意到,Bob在分配单位花费之前,已经知道Alice所给出的最大流方案。现茌Alice希望总费用尽量小,而Bob希望总费用尽量大。我们想知道,如果两个人都执行最优策略,最大流的值和总费用分别为多少。

    输入格式

    第一行三个整数N,M,P。N表示给定运输网络中节点的数量,M表示有向边的数量,P的含义见问题描述部分。为了简化问题,我们假设源点S是点1,汇点T是点N。
    接下来M行,每行三个整数A,B,C,表示有一条从点A到点B的有向边,其最大流量是C。
    

    输出格式

    第一行一个整数,表示最大流的值。
    第二行一个实数,表示总费用。建议选手输出四位以上小数。

    输入样例

    3 2 1

    1 2 10

    2 3 15

    输出样例

    10

    10.0000

    提示

    【样例说明】

    对于Alice,最大流的方案是固定的。两条边的实际流量都为10。
    
    对于Bob,给第一条边分配0.5的费用,第二条边分配0.5的费用。总费用
    

    为:100.5+100.5=10。可以证明不存在总费用更大的分配方案。

    【数据规模和约定】

    对于20%的测试数据:所有有向边的最大流量都是1。
    
    对于100%的测试数据:N < = 100,M < = 1000。
    
    对于l00%的测试数据:所有点的编号在I..N范围内。1 < = 每条边的最大流
    

    量 < = 50000。1 < = P < = 10。给定运输网络中不会有起点和终点相同的边。

    题解

    首先,Bob的最优策略一定是将所有权值加到流量最大的边上
    所以Alice应使在最大流前提下使最大流量的边最小

    那么二分所有边的上限判定可行性就可以了

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define eps 1e-8
    #define LL long long int
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
    using namespace std;
    const int maxn = 105,maxm = 5005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int n,m,h[maxn],ne = 2,S,T;
    double P,M;
    struct EDGE{int to,nxt; double f,cap;}ed[maxm];
    inline void build(int u,int v,double w){
    	ed[ne] = (EDGE){v,h[u],w,w}; h[u] = ne++;
    	ed[ne] = (EDGE){u,h[v],0,0}; h[v] = ne++;
    }
    int d[maxn],vis[maxn],cur[maxn];
    queue<int> q;
    bool bfs(){
    	for (int i = 1; i <= n; i++) d[i] = INF,vis[i] = false;
    	q.push(S); d[S] = 0; vis[S] = true;
    	int u;
    	while (!q.empty()){
    		u = q.front(); q.pop();
    		Redge(u) if (fabs(ed[k].f) > eps && !vis[to = ed[k].to]){
    			d[to] = d[u] + 1; vis[to] = true;
    			q.push(to);
    		}
    	}
    	return vis[T];
    }
    double dfs(int u,double minf){
    	if (u == T || fabs(minf) < eps) return minf;
    	double flow,f; int to;
    	if (cur[u] == -1) cur[u] = h[u];
    	for (int& k = cur[u]; k; k = ed[k].nxt)
    		if (d[to = ed[k].to] == d[u] + 1 && fabs(f = dfs(to,min(minf,ed[k].f))) > eps){
    			ed[k].f -= f; ed[k ^ 1].f += f;
    			flow += f; minf -= f;
    			if (fabs(minf) < eps) break;
    		}
    	return flow;
    }
    double maxflow(){
    	double flow = 0;
    	while (bfs()){
    		memset(cur,-1,sizeof(cur));
    		flow += dfs(S,INF);
    	}
    	return flow;
    }
    bool check(double cap){
    	for (int i = 2; i < ne; i += 2){
    		ed[i ^ 1].f = 0;
    		ed[i].f = min(ed[i].cap,cap);
    	}
    	return maxflow() >= M;
    }
    void solve(){
    	M = maxflow();
    	double l = 0,r = 50000,mid;
    	while ((r - l) > 1e-4){
    		mid = (l + r) / 2;
    		if (check(mid)) r = mid;
    		else l = mid;
    	}
    	printf("%.lf
    %.4lf
    ",M,l * P);
    }
    int main(){
    	n = read(); m = read(); P = read(); S = 1; T = n;
    	int a,b,w;
    	for (int i = 1; i <= m; i++){
    		a = read(); b = read(); w = read();
    		build(a,b,w);
    	}
    	solve();
    	return 0;
    }
    
    
  • 相关阅读:
    [Python] wxPython 高防Windows10记事本 (end...)
    C++模板学习:函数模板、结构体模板、类模板
    【English】十六、时间相关
    【English】十五、“a”和“one”的区别是什么?
    【English】十四、英语
    【English】十三、英语中的连词有哪些,都有什么作用
    【English】十二、英语句子种类,陈述句、疑问句、祈使句、感叹句
    【English】十一、一般疑问句
    【English】十、"谓语的地方"看到有两个动词:I go say hello.、非谓语形式
    【English】九、kids/children/toddlers 三个单词的区别
  • 原文地址:https://www.cnblogs.com/Mychael/p/8618511.html
Copyright © 2020-2023  润新知