[HDU 3599] 最短路 × 最大流

调这个题的时候发现了一点 多组数据的题目虽然很恶心但也是对一个人细致程度的检查, 特别是在这种很烦躁的时候是否还能静下心来check自己的代码
还有一个东西如果不优化能过的话最好不要优化, 这题加边本来可以用最暴力的方法 但是我之前想了些骚操作一直WA 改成暴力加边就过了…

好的步入正题 这道题实际上是一道比较简单的题目

因为题目要求最短路不相交 那么每条边就只能用一次 我们只需要对满足 dis[to[i]]==dis[x]+v[i] d i s [ t o [ i ] ] == d i s [ x ] + v [ i ] 的边 加一条从 xto[i] x 到 t o [ i ] 的边 然后跑 1n 1 到 n 的最大流就可以过了

一开始还有想过一个问题 那就是如果加进去的 不是最短路的边流出了一条路
但实际上是不可能的 因为从终点倒着往前推 那么所有
dis[to[i]]==dis[x]+v[i] d i s [ t o [ i ] ] == d i s [ x ] + v [ i ] 的边都是在最短路上的 那么就ok了
题目链接

#include
#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;
}

你可能感兴趣的:([HDU 3599] 最短路 × 最大流)