对网络流的建图又有了更深一步理解
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); }