先看isap的,这个是加了间隙优化的版本
Source Code
Problem: 1459 | User: forgotaboutdre | |
Memory: 948K | Time: 94MS | |
Language: G++ | Result: Accepted |
所谓间隙优化即指当某一个距离标号的数目为0时即返回当前流量。循环停止。
#include<cstdio>
#include<cstring>
#define size 270
#define inf 0x7ffff
int num[size], dis[size], pre[size];
int map[size][size], fanmap[size][size];
int n,np,nc,m;
int s, t;
int que[size];
int minc(int a, int b) {
if (a <= b)
return a;
return b;
}
void bfs(int t) {
memset(dis, 0, sizeof (dis));
memset(num,0,sizeof(num));
int head = 0, tail = 0;
que[head] = t;
num[0]=1;
while (head <= tail) {
int x = que[head];
for (int i = 0; i <= n+1; i++)
if (!dis[i] && map[i][x]) {
dis[i] = dis[x] + 1;
num[dis[i]]++;
que[++tail] = i;
if (i == s)
break;
}
head++;
}
}
int findalowarc(int i) {
for (int j = 0; j <= n+1; j++)
if (map[i][j]>0 && dis[i] == dis[j] + 1)
return j;
return -1;
}
int retreat(int i) {
int temp = inf;
for (int j = 0; j <= n+1; j++)
if (map[i][j] )
temp = minc(dis[j] + 1, temp);
if (temp != inf)
return temp;
return n+2;
}
int sap2(int s, int t) {
int flow=0,i=s,j;
int delt;
bfs(t);
memset(pre,-1,sizeof(pre));
while (dis[s]<n+2) {
if (findalowarc(i)>= 0) {
j = findalowarc(i);
pre[j] = i;
i = j;
if (i==t) {
delt = inf;
for (i = t; i != s; i = pre[i])
delt = minc(delt, map[pre[i]][i]);
for (i = t; i != s; i = pre[i]) {
map[pre[i]][i] -= delt;
map[i][pre[i]] += delt;
}
flow+=delt;
}
}
else
{
int x=retreat(i);
num[dis[i]]--;
num[x]++;
if(num[dis[i]]==0) return flow;
dis[i]=x;
if(i!=s) i=pre[i];
}
}
return flow;
}
int main()
{
char temp[20];
while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
{
memset(map,0,sizeof(map));
s=n;
t=n+1;
for(int i=0;i<m;i++)
{
int u,v,cost;
scanf("%s",temp);
sscanf(temp,"(%d,%d)%d",&u,&v,&cost);
map[u][v]+=cost;
}
for(int i=0;i<np;i++)
{
int u,c;
scanf("%s",temp);
sscanf(temp,"(%d)%d",&u,&c);
map[s][u]+=c;
}
for(int i=0;i<nc;i++)
{
int u,c;
scanf("%s",temp);
sscanf(temp,"(%d)%d",&u,&c);
map[u][t]+=c;
}
int ans=sap2(s,t);
printf("%d\n",ans);
}
return 0;
}
版本2,不加间隙优化。
但是初始数组用BFS初始化了。
Source Code
Problem: 1459 | User: yaws | |
Memory: 724K | Time: 157MS | |
Language: G++ | Result: Accepted |
#include<cstdio>
#include<cstring>
#define size 300
#define inf 0x7fffff
int dis[size], pre[size];
int map[size][size], fanmap[size][size];
int n, np, nc, m;
int s, t;
int que[size];
void bfs(int t) {
memset(dis, 0, sizeof (dis));
int head = 0, tail = 0;
que[head] = t;
while (head <= tail) {
int x = que[head];
for (int i = 0; i <= n + 1; i++)
if (!dis[i] && map[i][x]) {
dis[i] = dis[x] + 1;
que[++tail] = i;
if (i == s)
break;
}
head++;
}
}
int minc(int a, int b) {
if (a <= b)
return a;
return b;
}
int findalowarc(int i) {
for (int j = 0; j <= n + 1; j++)
if (map[i][j] > 0 && dis[i] == dis[j] + 1)
return j;
return -1;
}
int retreat(int i) {
int temp = inf;
for (int j = 0; j <= n + 1; j++)
if (map[i][j])
temp = minc(dis[j] + 1, temp);
if (temp != inf)
return temp;
return n + 2;
}
int sap(int s, int t) {
int flow = 0, i = s, j;
int delt;
bfs(t);
memset(pre, -1, sizeof (pre));
while (dis[s] < n + 2) {
if (findalowarc(i) >= 0) {
j = findalowarc(i);
pre[j] = i;
i = j;
if (i == t) {
delt = inf;
for (i = t; i != s; i = pre[i])
delt = minc(delt, map[pre[i]][i]);
for (i = t; i != s; i = pre[i]) {
map[pre[i]][i] -= delt;
map[i][pre[i]] += delt;
}
flow += delt;
}
} else {
int x = retreat(i);
dis[i] = x;
if (i != s)
i = pre[i];
}
}
return flow;
}
int main() {
char temp[20];
while (scanf("%d%d%d%d", &n, &np, &nc, &m) != EOF) {
memset(map, 0, sizeof (map));
s = n;
t = n + 1;
for (int i = 0; i < m; i++) {
int u, v, cost;
scanf("%s", temp);
sscanf(temp, "(%d,%d)%d", &u, &v, &cost);
map[u][v] += cost;
}
for (int i = 0; i < np; i++) {
int u, c;
scanf("%s", temp);
sscanf(temp, "(%d)%d", &u, &c);
map[s][u] += c;
}
for (int i = 0; i < nc; i++) {
int u, c;
scanf("%s", temp);
sscanf(temp, "(%d)%d", &u, &c);
map[u][t] += c;
}
int ans = sap(s, t);
printf("%d\n", ans);
}
return 0;
}
版本3 没有加间隙优化,dis数组没有用BFS初始化,全部设初值为0;
Source Code
Problem: 1459 | User: yaws | |
Memory: 724K | Time: 157MS | |
Language: G++ | Result: Accepted |
#include<cstdio>
#include<cstring>
#define size 300
#define inf 0x7fffff
int dis[size], pre[size];
int map[size][size], fanmap[size][size];
int n, np, nc, m;
int s, t;
int que[size];
int minc(int a, int b) {
if (a <= b)
return a;
return b;
}
int findalowarc(int i) {
for (int j = 0; j <= n + 1; j++)
if (map[i][j] > 0 && dis[i] == dis[j] + 1)
return j;
return -1;
}
int retreat(int i) {
int temp = inf;
for (int j = 0; j <= n + 1; j++)
if (map[i][j])
temp = minc(dis[j] + 1, temp);
if (temp != inf)
return temp;
return n + 2;
}
int sap(int s, int t) {
int flow = 0, i = s, j;
int delt;
memset(dis,0,sizeof(dis));
memset(pre, -1, sizeof (pre));
while (dis[s] < n + 2) {
if (findalowarc(i) >= 0) {
j = findalowarc(i);
pre[j] = i;
i = j;
if (i == t) {
delt = inf;
for (i = t; i != s; i = pre[i])
delt = minc(delt, map[pre[i]][i]);
for (i = t; i != s; i = pre[i]) {
map[pre[i]][i] -= delt;
map[i][pre[i]] += delt;
}
flow += delt;
}
} else {
int x = retreat(i);
dis[i] = x;
if (i != s)
i = pre[i];
}
}
return flow;
}
int main() {
char temp[20];
while (scanf("%d%d%d%d", &n, &np, &nc, &m) != EOF) {
memset(map, 0, sizeof (map));
s = n;
t = n + 1;
for (int i = 0; i < m; i++) {
int u, v, cost;
scanf("%s", temp);
sscanf(temp, "(%d,%d)%d", &u, &v, &cost);
map[u][v] += cost;
}
for (int i = 0; i < np; i++) {
int u, c;
scanf("%s", temp);
sscanf(temp, "(%d)%d", &u, &c);
map[s][u] += c;
}
for (int i = 0; i < nc; i++) {
int u, c;
scanf("%s", temp);
sscanf(temp, "(%d)%d", &u, &c);
map[u][t] += c;
}
int ans = sap(s, t);
printf("%d\n", ans);
}
return 0;
}
版本4
EK算法。。。。采用BFS寻找增广路,
Source Code
Problem: 1459 | User: yaws | |
Memory: 524K | Time: 313MS | |
Language: G++ | Result: Accepted |
#include<cstdio>
#include<cstring>
#define INF 100000
bool vis[250];
int map[205][205];
int que[1000];
int pre[205];
int n, np, nc, m, maxliu;
int s, t;
int minc(int a, int b) {
if (a <= b)
return a;
return b;
}
bool bfs(int s, int t) {
memset(vis, 0, sizeof (vis));
int head = 0, tail = 0;
que[head] = s;
vis[s] = true;
while (head <= tail) {
int soce = que[head];
for (int i = 0; i <= t; i++)
if (!vis[i] && map[soce][i]) {
que[++tail] = i;
vis[i] = true;
pre[i] = soce;
if (i == t)
return true;
}
head++;
}
return 0;
}
void maxflam() {
int limit = INF;
for (int i = t; i != s; i = pre[i])
limit = minc(limit, map[pre[i]][i]);
for (int i = t; i != s; i = pre[i]) {
map[pre[i]][i] -= limit;
map[i][pre[i]] += limit;
}
maxliu += limit;
}
int main() {
char temp[20];
while (scanf("%d%d%d%d", &n, &np, &nc, &m) != EOF) {
maxliu = 0;
memset(map, 0, sizeof (map));
s = n;
t = n + 1;
for (int i = 0; i < m; i++) {
int u, v, cost;
scanf("%s", temp);
sscanf(temp, "(%d,%d)%d", &u, &v, &cost);
map[u][v] += cost;
}
for (int i = 0; i < np; i++) {
int u, c;
scanf("%s", temp);
sscanf(temp, "(%d)%d", &u, &c);
map[s][u] += c;
}
for (int i = 0; i < nc; i++) {
int u, c;
scanf("%s", temp);
sscanf(temp, "(%d)%d", &u, &c);
map[u][t] += c;
}
while (bfs(s, t))
maxflam();
printf("%d\n", maxliu);
}
return 0;
}
总结:综上所述,sap算法的效率远高于EK,特别是加了间隙优化的sap,用BFS初始化距离标号其实没提高多少效率,可以忽略,反而能节省20行左右代码量。以后最大流就用sap吧。