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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【费用流】摘取作物(jozj 3447)

發(fā)布時間:2023/12/3 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【费用流】摘取作物(jozj 3447) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

正題

jozj 3447


題目大意

給你一個n*m的矩陣,每個位置有一個數(shù),每一行每一列都只能選兩個數(shù),問你所選數(shù)字之和最大是多少


解題思路

對于該矩陣,我們可以建立一個網(wǎng)絡(luò)圖(如下圖)

對于每一行建立建立一個點(下圖第一列),連向S,費用為0,流量為2
對于每一列建立一個點(下圖第二列),連向T,費用為0,流量為2
對于每個點連接相應(yīng)的行和列,費用為該點的數(shù)字大小,流量為1

建好網(wǎng)絡(luò)圖后,跑最大費用即可(注意這里不能直接跑費用流,流量不一定最大)

該題求最大費用,如果跑反邊,那么反邊的邊權(quán)絕對值會比上一條邊大,因為會先跑費用大的,所以不存在負(fù)權(quán)回路,可以用SPFA


代碼

#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 10000 using namespace std; const int inf = 1000000000; int n, m, x, w, s, t, tot, ans, v[N], vv[N], p[N], b[N], ls[N], nx[N], head[N]; queue<int>d; struct rec {int to, next, lst, val; }a[N]; void add(int x, int y, int z, int v) {a[++tot].to = y;a[tot].lst = z;a[tot].val = -v;a[tot].next = head[x];head[x] = tot;a[++tot].to = x;a[tot].lst = 0;a[tot].val = v;a[tot].next = head[y];head[y] = tot;return; } bool spfa() {memset(b, 127 / 3, sizeof(b));memset(p, 0, sizeof(p));memset(ls, 0, sizeof(ls));memset(nx, 0, sizeof(nx));while(!d.empty()) d.pop();p[s] = 1;b[s] = 0;ls[s] = inf;d.push(s);while(!d.empty()){int h = d.front();d.pop();for (int i = head[h]; i; i = a[i].next)if (b[h] + a[i].val < b[a[i].to] && a[i].lst){b[a[i].to] = b[h] + a[i].val;ls[a[i].to] = min(ls[h], a[i].lst);nx[a[i].to] = i;if (!p[a[i].to]){p[a[i].to] = 1;d.push(a[i].to);}}p[h] = 0;}return ls[t] > 0 && b[t] < 0;//保證費用大于0(這里建立負(fù)邊跑最短路) } void dfs() {int now = t;while(nx[now]){a[nx[now]].lst -= ls[t];a[nx[now]^1].lst += ls[t];now = a[nx[now]^1].to;}ans += b[t] * ls[t];return; } int main() {scanf("%d%d", &n, &m);tot = 1;s = ++w;t = ++w;for (int i = 1; i <= n; ++i)//建圖{v[i] = ++w;add(s, v[i], 2, 0);}for (int i = 1; i <= m; ++i){vv[i] = ++w;add(vv[i], t, 2, 0);}for (int i = 1; i <= n; ++i)for (int j = 1; j <= m; ++j){scanf("%d", &x);if (!x) continue;add(v[i], vv[j], 1, x);}while(spfa())dfs();printf("%d", -ans);return 0; }

總結(jié)

以上是生活随笔為你收集整理的【费用流】摘取作物(jozj 3447)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。