Baker Vai LightOJ - 1071 (MCMF)
在个给出的矩阵从,从左上角走到右下角,然后再从右下角走到左上角,两次不能经过想同的点,每个点都有一个价值,问最大的价值是多少。
可以把原来的问题化简成从左上角走两条路到右下角,然后把价值加起来,然是这时候我出发点和目标点的价值加了两次,而原本只计算一次,所以最后要减掉,然后建图
1.超源到(1,1), 容量inf,费用0
2.自身拆点,(1, 1)和(n, m)容量2,其他点容量1,费用就是本身的价值的负值
3.(n, m)到超汇,容量inf,费用0
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<map> #include<set> #include<ctime> #include<cmath> #include<stack> #include<queue> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define first fi #define second se #define lowbit(x) (x & (-x)) typedef unsigned long long int ull; typedef long long int ll; const double pi = 4.0*atan(1.0); const int inf = 0x3f3f3f3f; const int maxn = 10050; const int maxm = 100000; const int mod = 998244353; using namespace std; int n, m, tol, T; struct Node { int u; int v; int w; int val; int next; }; Node node[maxm]; int head[maxn]; int dis[maxn]; int pre[maxn]; int cap[maxn]; bool vis[maxn]; int maps[105][105]; void init() { tol = 0; memset(node, 0, sizeof node); memset(maps, 0, sizeof maps); memset(head, -1, sizeof head); } void addnode(int u, int v, int w, int val) { node[tol].u = u; node[tol].v = v; node[tol].w = w; node[tol].val = val; node[tol].next = head[u]; head[u] = tol++; } bool spfa(int src, int des, int &flow, int &cost) { memset(vis, 0, sizeof vis); memset(dis, inf, sizeof dis); memset(cap, inf, sizeof cap); queue<int > q; dis[src] = 0; cap[src] = inf; pre[src] = src; vis[src] = true; q.push(src); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for(int i=head[u]; ~i; i=node[i].next) { int v = node[i].v; if(node[i].w && dis[v] > dis[u] + node[i].val) { dis[v] = dis[u] + node[i].val; pre[v] = i; cap[v] = min(cap[u], node[i].w); if(!vis[v]) { vis[v] = true; q.push(v); } } } } if(dis[des] == inf) return false; flow += cap[des]; cost += cap[des] * dis[des]; int u = des; while(u != src) { node[pre[u]].w -= cap[des]; node[pre[u]^1].w += cap[des]; u = node[pre[u]].u; } return true; } int MCMF(int src, int des) { int flow = 0; int cost = 0; while(spfa(src, des, flow, cost)); return cost; } int main() { int cas = 1; scanf("%d", &T); while(T--) { init(); scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) scanf("%d", &maps[i][j]); int src = 0, des = 2*n*m+1; addnode(src, 1, inf, 0); addnode(1, src, 0, 0); addnode(2*n*m, des, inf, 0); addnode(des, 2*n*m, 0, 0); int cnt = n * m; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if((i==1 && j==1) || (i==n && j == m)) { addnode((i-1)*m+j, (i-1)*m+j+cnt, 2, -maps[i][j]); addnode((i-1)*m+j+cnt, (i-1)*m+j, 0, maps[i][j]); } else { addnode((i-1)*m+j, (i-1)*m+j+cnt, 1, -maps[i][j]); addnode((i-1)*m+j+cnt, (i-1)*m+j, 0, maps[i][j]); } if(i+1<=n) { addnode((i-1)*m+j+cnt, i*m+j, 1, 0); addnode(i*m+j, (i-1)*m+j+cnt, 0, 0); } if(j+1<=m) { addnode((i-1)*m+j+cnt, (i-1)*m+j+1, 1, 0); addnode((i-1)*m+j+1, (i-1)*m+j+cnt, 0, 0); } } } int ans = -MCMF(src, des) - maps[1][1] - maps[n][m]; printf("Case %d: %d\n", cas++, ans); } return 0; }