调这个题的时候发现了一点 多组数据的题目虽然很恶心但也是对一个人细致程度的检查, 特别是在这种很烦躁的时候是否还能静下心来check自己的代码
还有一个东西如果不优化能过的话最好不要优化, 这题加边本来可以用最暴力的方法 但是我之前想了些骚操作一直WA 改成暴力加边就过了…
好的步入正题 这道题实际上是一道比较简单的题目
因为题目要求最短路不相交 那么每条边就只能用一次 我们只需要对满足dis[to[i]]==dis[x]+v[i] d i s [ t o [ i ] ] == d i s [ x ] + v [ i ]的边 加一条从x到to[i] x 到 t o [ i ]的边 然后跑1到n 1 到 n的最大流就可以过了
一开始还有想过一个问题 那就是如果加进去的 不是最短路的边流出了一条路
但实际上是不可能的 因为从终点倒着往前推 那么所有
dis[to[i]]==dis[x]+v[i] d i s [ t o [ i ] ] == d i s [ x ] + v [ i ]的边都是在最短路上的 那么就ok了
题目链接
#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define go(x, i) for(register int i = head[x]; i; i = nxt[i])
#define inf (0x3f3f3f3f)
using namespace std;
const int maxn = 1500 + 10, maxm = maxn * maxn;
int to[maxm], head[maxn], nxt[maxm], v[maxm], e, from[maxm];
int dis[maxn], vis[maxn], n;
queue<int> pre[maxn];
void add(int x, int y, int z) {
to[++ e] = y;
from[e] = x;
nxt[e] = head[x];
head[x] = e;
v[e] = z;
}
void SPFA() {
queue<int> q;
For(i, 1, n) dis[i] = inf, clear(pre[to[i]]);
dis[1] = 0, q.push(vis[1] = 1);
while(!q.empty()) {
int k = q.front(); q.pop();
go(k, i) {
if(dis[to[i]] > dis[k] + v[i]) {
dis[to[i]] = dis[k] + v[i];
if(!vis[to[i]]) q.push(vis[to[i]] = to[i]);
clear(pre[to[i]]);
}
if(dis[to[i]] == dis[k] + v[i])
pre[to[i]].push(k);
}
vis[k] = 0;
}
}
namespace Max_flow {
int to[maxm], head[maxn], nxt[maxm], w[maxm], e = 1, dis[maxn];
void add(int x, int y, int z) {
to[++ e] = y;
nxt[e] = head[x];
head[x] = e;
w[e] = z;
if(z) add(y, x, 0);
}
bool bfs() {
queue<int> q;
For(i, 1, n) dis[i] = 0;
q.push(dis[1] = 1);
while(!q.empty()) {
int k = q.front(); q.pop();
go(k, i)
if(!dis[to[i]] && w[i]) {
dis[to[i]] = dis[k] + 1;
q.push(to[i]);
}
}
return dis[n];
}
int dfs(int x, int flow) {
if(x == n || !flow)
return flow;
int used = 0;
go(x, i)
if(dis[to[i]] == dis[x] + 1 && w[i]) {
int di = dfs(to[i], min(flow, w[i]));
w[i] -= di, w[i ^ 1] += di;
flow -= di, used += di;
if(!flow) break;
}
return used;
}
int solve() {
int res = 0, flow;
while(bfs())
while(flow = dfs(1, inf))
res += flow;
For(i, 1, n) head[i] = 0; e = 1;
return res;
}
}
void add_edge() {
For(i, 1, e)
if(dis[to[i]] == dis[from[i]] + v[i])
Max_flow::add(from[i], to[i], 1);
}
int main() {
// freopen("3599.in", "r", stdin);
// freopen("3599.out", "w", stdout);
int T, x, y, z;
for(scanf("%d", &T); T -- ; ) {
For(i, 1, n) head[i] = 0; e = 0;
scanf("%d", &n);
while(true) {
scanf("%d%d%d", &x, &y, &z);
if(x + y + z == 0) break;
add(x, y, z), add(y, x, z);
}
if(n == 1) {
puts("0");
continue;
}
SPFA(), add_edge();
printf("%d\n", Max_flow::solve());
}
return 0;
}
版权声明:本文为lunch__原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。