对网络流的建图又有了更深一步理解
http://pan.baidu.com/share/link?shareid=1648064038&uk=1090822741
看了这个以后。
大概思路就是吧多元关系转化成两元关系,每个点多加两个收益点(一个表示放本位置收益,一个表示放周围收益),两个收益点分别连源点汇点(为了控制两个收益互斥)
然后就是二元关系,剩下建图就很常规了,也用不到上面论文中的解方程。
题解貌似是另一种方法,明天再看!
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
using namespace std;
class SurroundingGame {
public:
int maxScore(vector<string> , vector<string> );
};
#define N 20009
#define M 2000009
#define inf 2000000000
#define INT int
struct E {
int t, next;
INT flow, cap;
} edge[M];
int node[N], eid;
vector<int> e[N];
int rr[N];
int que[N];
void init() {
eid = 0;
memset(rr, -1, sizeof(rr));
memset(node, -1, sizeof(node));
}
void addedge(int a, int b, INT c) {
edge[eid].t = b;
edge[eid].cap = c;
edge[eid].flow = 0;
edge[eid].next = node[a];
node[a] = eid++;
edge[eid].t = a;
edge[eid].cap = 0; //0单向,c双向
edge[eid].flow = 0;
edge[eid].next = node[b];
node[b] = eid++;
}
void addedge1(int a, int b, INT c) {
edge[eid].t = b;
edge[eid].cap = c;
edge[eid].flow = 0;
edge[eid].next = node[a];
node[a] = eid++;
edge[eid].t = a;
edge[eid].cap = c; //0单向,c双向
edge[eid].flow = 0;
edge[eid].next = node[b];
node[b] = eid++;
}
int bfs(int s, int t, int n) {
memset(rr, -1, sizeof(rr));
int i;
for (i = 0; i < n; ++i)
e[i].clear();
int u, v;
int front = 0, rear = 1;
rr[s] = 0;
que[0] = s;
while (rear > front) {
u = que[front++];
for (i = node[u]; i != -1; i = edge[i].next) {
v = edge[i].t;
if (rr[v] == -1 && edge[i].cap) {
que[rear++] = v;
rr[v] = rr[u] + 1;
}
if (rr[v] == rr[u] + 1)
e[u].push_back(i);
}
}
return (rr[t] != -1);
}
INT dinic(int s, int t, int n) {
int st[N];
INT maxflow = 0;
int aux[N];
int top, cur;
int p, i, k;
while (bfs(s, t, n)) {
top = 0;
st[top] = s;
cur = s;
while (1) {
if (cur == t) {
INT minc = inf;
for (i = 0; i < top; ++i) {
p = aux[i + 1];
if (minc > edge[p].cap)
minc = edge[p].cap, k = i;
}
for (i = 0; i < top; ++i) {
p = aux[i + 1];
edge[p].cap -= minc;
edge[p ^ 1].cap += minc;
}
maxflow += minc;
cur = st[top = k];
}
int len = e[cur].size();
while (len) {
p = e[cur][len - 1];
if (edge[p].cap && rr[edge[p].t] == rr[cur] + 1)
break;
else {
len--;
e[cur].pop_back();
}
}
if (len) {
cur = st[++top] = edge[p].t;
aux[top] = p;
} else {
if (top == 0)
break;
rr[cur] = -1;
cur = st[--top];
}
}
}
return maxflow;
}
int f(char c) {
if ('0' <= c && '9' >= c)
return c - '0';
if ('a' <= c && 'z' >= c)
return c - 'a' + 10;
if ('A' <= c && 'Z' >= c)
return c - 'A' + 36;
}
int dir[4][2] = { 0, 1, 1, 0, 0, -1, -1, 0 };
int SurroundingGame::maxScore(vector<string> cost, vector<string> benefit) {
int i, j, k;
int ans;
int n = cost.size();
int m = cost[0].size();
int s, t;
s = 3 * n * m;
t = s + 1;
ans = 0;
init();
for (i = 0; i < n; ++i) {
for (j = 0; j < m; ++j) {
ans += 2 * f(benefit[i][j]);
if ((i + j) % 2) {
addedge(s, i * m + j, f(cost[i][j]));
addedge(i * m + j + n * m, t, f(benefit[i][j]));
addedge(s, i * m + j + n * m * 2, f(benefit[i][j]));
addedge(i * m + j, i * m + j + n * m, inf);
addedge(i * m + j + n * m * 2, i * m + j + n * m, inf);
} else {
addedge(i * m + j, t, f(cost[i][j]));
addedge(i * m + j + n * m, t, f(benefit[i][j]));
addedge(s, i * m + j + n * m * 2, f(benefit[i][j]));
addedge(i * m + j + n * m * 2, i * m + j, inf);
addedge(i * m + j + n * m * 2, i * m + j + n * m, inf);
}
}
}
for (i = 0; i < n; ++i) {
for (j = 0; j < m; ++j) {
for (k = 0; k < 4; ++k) {
int ii = i + dir[k][0];
int jj = j + dir[k][1];
if (ii < 0 || jj < 0 || ii >= n || jj >= m)
continue;
if ((i + j) % 2) {
addedge(i * m + j + n * m * 2, ii * m + jj, inf);
} else {
addedge(ii * m + jj, i * m + j + n * m, inf);
}
}
}
}
return ans - dinic(s, t, t + 1);
}