• [01分数规划二分]网络战争


    网络战争

    给一个无向图 (G=(V,E)) ,求一个边集 (C) ,删除 (C)(s)(t) 不再连通

    最小化

    [dfrac {sum_{ein C}w_e} {|C|} ]

    01分数规划

    每个物品价值 (w_i) , 花费 (c_i)

    选一些物品使得

    (dfrac{sum w} {sum c}) 最小

    [dfrac {sum w} {sum c} < lambda \ sum w - lambda sum c < 0 \ sum_i (w_i - lambda c_i) < 0 ]

    至此,可以二分答案 (lambda)

    /*
     * @Author: zhl
     * @Date: 2020-10-22 15:44:57
     */
    
    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i = a;i <= b;i++)
    #define repE(i,u) for(int i = head[u]; ~i; i = E[i].next)
    using namespace std;
    
    const int N = 2100, M = 10100, inf = 1e9;
    struct Edge {
    	int to, next;
    	double flow;
    }E[M << 1];
    int head[N], tot;
    void addEdge(int from, int to, double w) {
    	E[tot] = Edge{ to,head[from],w };
    	head[from] = tot++;
    	E[tot] = Edge{ from,head[to],0.0 };
    	head[to] = tot++;
    }
    
    int n, m, s, t;
    queue<int>Q;
    int dis[N], cur[N];
    bool bfs() {
    	memset(dis, -1, sizeof dis);
    	while (!Q.empty())Q.pop();
    	Q.push(s); dis[s] = 0; cur[s] = head[s];
    	while (!Q.empty()) {
    		int u = Q.front(); Q.pop();
    		repE(i, u) {
    			int v = E[i].to;
    			if (dis[v] == -1 and E[i].flow) {
    				cur[v] = head[v];
    				dis[v] = dis[u] + 1;
    				Q.push(v);
    				if (v == t)return true;
    			}
    		}
    	}
    	return false;
    }
    
    double dfs(int u, double limit) {
    	if (u == t)return limit;
    	double k, res = 0;
    	for (int i = cur[u]; ~i and res < limit; i = E[i].next) {
    		int v = E[i].to;
    		cur[u] = i;
    		if (dis[v] == dis[u] + 1 and E[i].flow) {
    			k = dfs(v, min(limit - res, E[i].flow));
    			if (k == 0)dis[v] = -1;
    			E[i].flow -= k; E[i ^ 1].flow += k;
    			res += k;
    		}
    	}
    	return res;
    }
    
    double Dinic() {
        double res = 0, f;
    	while (bfs())while (f = dfs(s, inf)) res += f;
    	return res;
    }
    
    const double eps = 1e-4;
    int u[N],v[N],w[N];
    
    bool judge(double x){
        memset(head,-1,sizeof head);
        tot = 0;
        double sum = 0;
        rep(i,1,m){
            if(w[i] <= x) sum += w[i] - x;
            else addEdge(u[i],v[i],w[i]-x),addEdge(v[i],u[i],w[i]-x);
        }
        return Dinic() + sum <= 0;
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&s,&t);
        rep(i,1,m){
            scanf("%d%d%d",u+i,v+i,w+i);
        }
        double l = 0,r = 1e7;
        while(r - l > eps){
            double mid = (l + r) / 2;
            if(judge(mid))r = mid;
            else l = mid;
        }
        printf("%.2f
    ",l);
    }
    
  • 相关阅读:
    SQL_Server_2005_字符串函数(描述及实例)
    固定在左右两侧不动的广告条 样式
    jquery 浏览器判断
    sqlserver 2005无限极分类 获取 所有子分类
    asp.net使用treeview控件,递归加载
    C++day15 学习笔记
    Win32编程day02 学习笔记
    Win32编程day04 学习笔记
    C++day16 学习笔记
    Win32编程day05 学习笔记
  • 原文地址:https://www.cnblogs.com/sduwh/p/13878958.html
Copyright © 2020-2023  润新知