题意:
给出点与边,求两条不重边的最短路径
思路:
用网络流控制数量为两条(cap控制),保证以最小流连贯到底,其实就是控制次数,map保证每条路一次
要注意的是,走过的路径中反向的map为原先的负数,道理和网络流的对称性一致
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 105;
const int INF = 0x3f3f3f3f;
int n, m;
int map[maxn][maxn];
int dis[maxn];
int p[maxn];
int vis[maxn];
int cap[maxn][maxn];
int flow[maxn][maxn];
int k[maxn];
void spfa() {
queue<int> q;
int ans = 0;
int f = 0;
memset(p, 0, sizeof(0));
while(1) {
q.push(0);
memset(vis, 0, sizeof(vis));
memset(k, 0, sizeof(k));
k[0] = INF;
for(int i=0; i<=n+1; i++) dis[i] = INF;
dis[0] = 0;
while(!q.empty()) {
int u = q.front();
q.pop();
vis[u] = 0;
for(int i=0; i<=n+1; i++) {
if(dis[i]>dis[u]+map[u][i] && cap[u][i]>flow[u][i]) {
k[i] = min(k[u], cap[u][i]-flow[u][i]);
dis[i] = dis[u]+map[u][i];
p[i] = u;
if(vis[i] == 0) {
vis[i] = 1;
q.push(i);
}
}
}
}
if(k[n+1] == 0) break;
for(int i=n+1; i; i=p[i]) {
map[p[i]][i] = INF;
map[i][p[i]] = -map[i][p[i]];
}
for(int i=n+1; i; i=p[i]) {
flow[p[i]][i] += k[n+1];
flow[p[i]][i] -= k[n+1];
}
map[0][1] = 0;
map[n][n+1] = 0;
ans += dis[n+1];
f += k[n+1];
if(f==2) break;
}
if(f==2)
printf("%d\n",ans);
else printf("Back to jail\n");
}
int main() {
while(scanf("%d", &n) && n) {
int a, b, c;
scanf("%d", &m);
memset(cap, 0, sizeof(cap));
memset(flow, 0, sizeof(flow));
for(int i=0; i<m; i++) {
scanf("%d%d%d", &a, &b, &c);
map[a][b] = map[b][a] = c;
cap[a][b] = 1;
cap[b][a] = 1;
}
map[0][1] = 0;
cap[0][1] = 2;
cap[1][0] = 0;
map[n][n+1] = 0;
cap[n][n+1] = 2;
cap[n+1][n] = 0;
spfa();
}
return 0;
}
更简单的方法:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 105;
const int INF = 0x3f3f3f3f;
int n, m;
int map[maxn][maxn];
int dis[maxn];
int p[maxn];
int vis[maxn];
int cap[maxn][maxn];
int flow[maxn][maxn];
int k[maxn];
void spfa() {
queue<int> q;
int ans = 0;
int f = 0;
int count = 0;
while(1) {
memset(p, 0, sizeof(0));
q.push(0);
memset(vis, 0, sizeof(vis));
memset(k, 0, sizeof(k));
k[0] = INF;
for(int i=0; i<=n+1; i++) dis[i] = INF;
dis[0] = 0;
while(!q.empty()) {
int u = q.front();
q.pop();
vis[u] = 0;
for(int i=0; i<=n+1; i++) {
if(dis[i]>(dis[u]+map[u][i])) {
p[i] = u;
dis[i] = dis[u]+map[u][i];
if(vis[i] == 0) {
vis[i] = 1;
q.push(i);
}
}
}
}
if(dis[n+1]==INF) break;
count ++;
for(int i=n+1; i; i=p[i]) {
map[p[i]][i] = INF;
map[i][p[i]] = -map[i][p[i]];
}
map[0][1] = 0;
map[1][0] = INF;
map[n][n+1] = 0;
map[n+1][n] = INF;
ans += dis[n+1];
if(count==2) break;
}
if(count==2)
printf("%d\n",ans);
else printf("Back to jail\n");
}
int main() {
while(scanf("%d", &n) && n) {
int a, b, c;
scanf("%d", &m);
memset(cap, 0, sizeof(cap));
memset(flow, 0, sizeof(flow));
memset(map, INF, sizeof(map));
for(int i=0; i<m; i++) {
scanf("%d%d%d", &a, &b, &c);
map[a][b] = map[b][a] = c;
cap[a][b] = 1;
cap[b][a] = 1;
}
map[0][1] = 0;
cap[0][1] = 2;
cap[1][0] = 0;
map[n][n+1] = 0;
cap[n][n+1] = 2;
cap[n+1][n] = 0;
spfa();
}
return 0;
}