SAP的模板题,主要是输入有点难处理,看有人用sscanf函数处理的,我是直接对字符串进行处理的。
对于SAP:其实核心思想就是高度函数,把它搞懂SAP其实和EK算法本质上是一样的。
还有一个重要的是GAP优化,即当高度出现断层时算法结束。
#include<stdio.h>
#include<string.h>
const int N = 128;
const int INF = 0x3f3f3f3f;
struct Edge {
int v, next;
int c;
};
Edge edge[N*N<<2];
int h[N], numh[N], pre[N], curEdge[N];
int n, np, nc, m, cnt;
int fir[N];
void init() {
cnt = 0;
memset(fir, -1, sizeof(fir));
}
void addEdge(int u, int v, int c) {
edge[cnt].v = v;
edge[cnt].c = c;
edge[cnt].next = fir[u];
fir[u] = cnt++;
}
int SAP(int s, int e) {
memset(h, 0, sizeof(h));
memset(numh, 0, sizeof(numh));
memset(pre, -1, sizeof(pre));
for(int i = 0; i < n; i++)
curEdge[i] = fir[i];
numh[0] = n;
int i;
int cur = s, pos, mmin, maxflow = 0;
while(h[s] < n) {
if(cur == e) {
mmin = INF;
for(i = s; i != e; i = edge[curEdge[i]].v) {
if(mmin > edge[curEdge[i]].c) {
mmin = edge[curEdge[i]].c;
pos = i;
}
}
; for(i = s; i != e; i = edge[curEdge[i]].v) {
edge[curEdge[i]].c -= mmin;
edge[curEdge[i]^1].c += mmin;
}
maxflow += mmin;
cur = pos;
}
for(i = curEdge[cur]; i != -1; i = edge[i].next)
if(edge[i].c && h[cur] == h[edge[i].v] + 1)
break;
if(i != -1) {
curEdge[cur] = i;
pre[edge[i].v] = cur;
cur = edge[i].v;
} else {
if(--numh[h[cur]] == 0) break;
mmin = n;
curEdge[cur] = fir[cur];
for(i = fir[cur]; i != -1; i = edge[i].next) {
if(edge[i].c && h[edge[i].v] < mmin)
mmin = h[edge[i].v];
}
h[cur] = mmin + 1;
numh[h[cur]] ++;
if(cur != s) cur = pre[cur];
}
}
return maxflow;
}
int main() {
char in[16];
while(~scanf("%d%d%d%d", &n, &np, &nc, &m)) {
int a, b, c;
init();
for(int i = 0; i < m; i++) {
scanf("%s", in);
a = b = c = 0;
int bas = 1;
int len = strlen(in);
while(in[--len] != ')') {
c += (in[len] - '0') * bas;
bas *= 10;
}
bas = 1;
while(in[--len] != ',') {
b += (in[len] - '0') * bas;
bas *= 10;
}
bas = 1;
while(in[--len] != '(') {
a += (in[len] - '0') * bas;
bas *= 10;
}
addEdge(a, b, c);
addEdge(b, a, 0);
}
for(int i = 0; i < np; i++) {
scanf("%s", in);
a = c = 0;
int len = strlen(in);
int bas = 1;
while(in[--len] != ')') {
c += (in[len] - '0') * bas;
bas *= 10;
}
bas = 1;
while(in[--len] != '(') {
a += (in[len] - '0') * bas;
bas *= 10;
}
addEdge(n, a, c);
addEdge(a, n, 0);
}
for(int i = 0; i < nc; i++) {
scanf("%s", in);
a = c = 0;
int len = strlen(in);
int bas = 1;
while(in[--len] != ')') {
c += (in[len] - '0') * bas;
bas *= 10;
}
bas = 1;
while(in[--len] != '(') {
a += (in[len] - '0') * bas;
bas *= 10;
}
addEdge(a, n+1, c);
addEdge(n+1, a, 0);
}
n += 2;
printf("%d\n", SAP(n-2, n-1));
}
return 0;
}