[01分數規劃二分]網路戰爭
阿新 • • 發佈:2020-10-26
網路戰爭
給一個無向圖 \(G=(V,E)\) ,求一個邊集 \(C\) ,刪除 \(C\) 後 \(s\) ,\(t\) 不再連通
最小化
\[\dfrac {\sum_{e\in C}w_e} {|C|} \]01分數規劃
\[\dfrac {\sum w} {\sum c} < \lambda \\ \sum w - \lambda \sum c < 0 \\ \sum_i (w_i - \lambda c_i) < 0 \]每個物品價值 \(w_i\) , 花費 \(c_i\)
選一些物品使得
\(\dfrac{\sum w} {\sum c}\) 最小
至此,可以二分答案
/* * @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\n",l); }