H.Minimum-cost Flow
生活随笔
收集整理的這篇文章主要介紹了
H.Minimum-cost Flow
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
H.Minimum-cost Flow
題目:
其實就是給出每條邊的單位費用,q次查詢,每次查詢改變所有邊的容量(所有邊容量一樣),問最后流出1流量的最小花費是多少?
題解:
暴力做法肯定是每次詢問都改一次容量,但是肯定會超時,想想其他方法
對于題目的每次詢問,每條增廣路的容量為u/v,所需最大流是1,我們可以列出一個式子
cost(u/v,1) = cost(u,v)
也就是把問題變成每條容量為u,所需要的最大流為v
為了達到最大流為v的要求,肯定有a條增廣路容量用完,但也肯定會有一個增廣路只用了部分(假設用了b容量)0<=b<u
能得到:v = a * u + b(0<=b<u)
所以我們只需要求出前a條增廣路的全部和第a+1條增廣路的b容量
然后記得判斷流出的流量要大于等于v才可以,不足v就輸出NaN
因為跑得最小費用最大流,這樣的答案一定是最優答案
代碼:
#include<bits/stdc++.h>using namespace std; #define lowbit(x) ((x)&(-x)) #define REP(i, a, n) for(int i=a;i<=(n);i++) #define IOS ios::sync_with_stdio(false),cin.tie(0), cout.tie(0) typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> P;const int maxn = 1e5 + 10; const int N = 1e2 + 10; const int M = 1e3 + 10; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const int mod2 = 998244353; const int mod3 = 1e9 + 9; const int hash1 = 131; const int hash2 = 13331; const double eps = 1e-6; int head[N], ver[M], nxt[M], edge[M], cost[M]; int tot = 1; int d[N], incf[N], pre[N]; int vis[N];void add(int x, int y, int z, int c) {ver[++tot] = y, edge[tot] = z, cost[tot] = c, nxt[tot] = head[x], head[x] = tot;ver[++tot] = x, edge[tot] = 0, cost[tot] = -c, nxt[tot] = head[y], head[y] = tot; }int s, t; vector<int> path;bool spfa() {queue<int> q;memset(d, inf, sizeof(d));memset(vis, 0, sizeof(vis));q.push(s);d[s] = 0, vis[s] = 1;incf[s] = 1 << 30;while (!q.empty()){int x = q.front();q.pop();vis[x] = 0;for (int i = head[x]; i; i = nxt[i]){if (!edge[i])continue;int y = ver[i];if (d[y] > d[x] + cost[i]){d[y] = d[x] + cost[i];incf[y] = min(incf[x], edge[i]);pre[y] = i;if (!vis[y])vis[y] = 1, q.push(y);}}}if (d[t] == inf)return false;return d[t]; }int maxflow, ans;void update() {path.push_back(d[t]);//記錄每條增廣路的花費int x = t;while (x != s){int i = pre[x];edge[i] -= incf[t];edge[i ^ 1] += incf[t];x = ver[i ^ 1];}maxflow += incf[t];ans += d[t] * incf[t];}ll sumd[N];int main() {int n, m;while (scanf("%d%d", &n, &m) != EOF){path.clear();memset(head, 0, sizeof(head));tot = 1;for (int i = 1; i <= m; i++){int a, b, c;scanf("%d%d%d", &a, &b, &c);add(a, b, 1, c);}s = 1, t = n;while (spfa())update();for (int i = 0; i < path.size(); i++){sumd[i + 1] = sumd[i] + path[i];//前i條增廣路的花費 }int q;scanf("%d", &q);int u, v;for (int i = 1; i <= q; i++){scanf("%d%d", &u, &v);if (u * path.size() < v){puts("NaN");continue;}ll a = v / u;ll b = v % u;ll ans = sumd[a] * u + path[a] * b;ll x = __gcd((ll) v, ans);printf("%lld/%lld\n", ans / x, v / x);}}return 0; }總結
以上是生活随笔為你收集整理的H.Minimum-cost Flow的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原生JS的拖拽属性draggable(详
- 下一篇: B-Suffix Array