日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU - 6598 Harmonious Army (最小割)

發布時間:2024/4/18 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU - 6598 Harmonious Army (最小割) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接

題意

每個人可以選擇兩種角色(A,B)(A, B)(A,B),給定MMM個關系(x,y)(x, y)(x,y),如果x,yx, yx,y同時選擇AAA總的攻擊力加aaa,如果x,yx, yx,y同時選擇BBB總的攻擊力加ccc,如果x,yx, yx,y分別選擇A,BA,BAB總的攻擊力加ccc,求如何分配使得總的攻擊力最大?

思路

轉化為最小割模型,統計所有流量,構造使得最小割為多加的流量,邊權擴大2倍,防止小數。
(來自題解)

設一條邊的三種貢獻為 A,B,CA,B,CABC,可以得到以下方程:

a+b=A+Ba + b = A + Ba+b=A+Bx,yx, yxy 都選 Mage)

c+d=C+Bc + d = C + Bc+d=C+Bx,yx, yxy 都選 Warrior)

a+d+e=A+Ca + d + e = A + Ca+d+e=A+Cxxx 選 Mage, yyy 選 Warrior )

b+c+e=A+Cb + c + e = A + Cb+c+e=A+Cxxx 選 Warrior, yyy 選 Mage )

可得一組解 a=b=(A+B)/2,c=d=(C+B)/2,e=?B+(A+C)/2a = b =(A + B)/ 2, c = d = (C + B) / 2, e = -B + (A + C) / 2a=b=A+B/2c=d=(C+B)/2,e=?B+(A+C)/2 ,然后將所有有關系的兩點的圖合并,用所有貢獻減掉這個圖的最小割即可。

#include <bits/stdc++.h> #define endl '\n' const int maxn = 5e2 + 5; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; using namespace std; struct Dinic{struct ac{int v, c, nex;}edge[maxn << 7]; // 根據題目要求計算int s, e;int head[maxn], dis[maxn], curedge[maxn], cnt;void init() {cnt = 0;memset(head, -1, sizeof(head));}void add(int u, int v, int c) {// 正向建邊edge[cnt] = {v, c, head[u]};head[u] = cnt++;// 反向建邊, 流量為0edge[cnt] = {u, 0, head[v]};head[v] = cnt++;}bool bfs() {queue<int> que;que.push(s);memset(dis, 0, sizeof(dis)); // 對圖進行分層dis[s] = 1;while (!que.empty()) {int u = que.front();que.pop();for (int i = head[u]; i != -1; i = edge[i].nex) {int v = edge[i].v;int c = edge[i].c;// 如果節點v已經分過層或者u->v流量為0, continueif (dis[v] || c == 0) continue;dis[v] = dis[u] + 1; // 對v進行標記并加入隊列que.push(v);}}return dis[e] > 0; // 判斷是否存在增廣路,s是否能到達e}int dfs(int u, int flow) { // 增廣路走到u點的最小流量為flowif (u == e || flow == 0) return flow;// 遍歷u的所有出邊for (int &i = curedge[u]; i != -1; i = edge[i].nex) { // 當前弧優化int v = edge[i].v;int c = edge[i].c;// 判斷能否u->v增廣if (dis[v] != dis[u] + 1 || c == 0) continue;int d = dfs(v, min(flow, c));if (d > 0) { // 找到一條增廣路,修改增廣路上的正反向邊edge[i].c -= d;edge[i^1].c += d;return d;} }dis[u] = -1; // // 炸點優化return 0;}long long dinic() {long long sum = 0, d;while (bfs()) { // 判讀是否存在增廣路for (int i = 0; i <= e; ++i) curedge[i] = head[i]; // copy head數組,在dfs中可以直接得到下一條沒有被增廣過的邊while ((d = dfs(s, inf)) > 0) sum += d; // 多次dfs找增廣路}return sum;} }D; int L[maxn], R[maxn]; int main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int n, m, s, e;while (scanf("%d %d", &n, &m) != EOF) {D.s = s = 0, D.e = e = n + 1;D.init();int u, v, a, b, c;long long ans = 0;fill(L, L+n+1, 0);fill(R, R+n+1, 0);for (int i = 0; i < m; ++i) {scanf("%d %d %d %d %d", &u, &v, &a, &b, &c);ans += a + b + c;D.add(u, v, a + c - 2*b);D.add(v, u, a + c - 2*b);L[u] += b + c;L[v] += b + c;R[u] += a + b;R[v] += a + b;}for (int i = 1; i <= n; ++i) {D.add(s, i, L[i]);D.add(i, e, R[i]);}ans = ans * 2 - D.dinic();printf("%lld\n", ans / 2);}return 0; } 與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的HDU - 6598 Harmonious Army (最小割)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。