Marriage Match IV HDU

题意

给你n个点,m条边,要求每条边只能走一次的S到T的最短路径的个数


题解

在我又WA又TLE还RE时,yyb大佬告诉我说要跑两遍SPFA,还说我写的一遍SPFA是错的,然而

啪啪打脸。。。
而且他的

比我跑得慢,2333
接下来讲一下方法
首先一遍SPFA(或dijkstra)从S跑一遍到所有点的最短路,重新建图时对于每对u, v 若 dis[u] + w[u][v] == dis[v] 则加入这条边,容量为1(还要加反边),最后跑最大流即可,最大流我用的是Dinic,然后注意手打队列,系统的会TLE


常熟巨大的丑陋代码

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define ll long long
# define mem(a, b) memset(a, b, sizeof(a))
# define Min(a, b) (((a) > (b)) ? (b) : (a))
# define Max(a, b) (((a) < (b)) ? (b) : (a))
using namespace std;

IL int Get(){
    RG char c = '!'; RG int x = 0, z = 1;
    for(; c > '9' || c < '0'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c <= '9' && c >= '0'; c = getchar()) x = x * 10 + c - '0';
    return x * z;
}

const int MAXN = 1001, MAXM = 200001, INF = 2147483647;
int n, m, ft[MAXN], cnt, ans, dis[MAXN], vis[MAXN], _ft[MAXN], level[MAXN], Q[MAXM];
struct Edge{
    int to, f, nt;
} edge[MAXM], _edge[MAXM];

IL void Add(RG int u, RG int v, RG int f){
    edge[cnt] = (Edge){v, f, ft[u]}; ft[u] = cnt++;
}

IL void Add2(RG int u, RG int v, RG int f){
    _edge[cnt] = (Edge){v, f, _ft[u]}; _ft[u] = cnt++;
}

IL void SPFA(RG int S, RG int T){
    RG int head = 0, tail = 0;
    Q[0] = S; vis[S] = 1; dis[S] = 0;
    while(head <= tail){
        RG int u = Q[head++]; vis[u] = 0;
        for(RG int e = ft[u]; e != -1; e = edge[e].nt){
            RG int v = edge[e].to, f = edge[e].f + dis[u];
            if(dis[v] > f){
                dis[v] = f;
                if(!vis[v]) vis[v] = 1, Q[++tail] = v;
            }
        }
    }
}

IL bool Bfs(RG int S, RG int T){
    mem(level, 0);
    RG int head = 0, tail = 0;
    Q[0] = S; level[S] = 1;
    while(head <= tail){
        RG int u = Q[head++];
        if(u == T) return 1;
        for(RG int e = _ft[u]; e != -1; e = _edge[e].nt){
            RG int v = _edge[e].to, f = _edge[e].f;
            if(f && !level[v]){
                level[v] = level[u] + 1;
                Q[++tail] = v;
            }
        }
    }
    return 0;
}

IL int Dfs(RG int u, RG int T, RG int maxf){
    if(u == T) return maxf;
    RG int res = 0;
    for(RG int e = _ft[u]; e != -1; e = _edge[e].nt){
        RG int v = _edge[e].to, f = _edge[e].f;
        if(level[u] + 1 == level[v] && f){
            f = Dfs(v, T, Min(f, maxf - res));
            _edge[e].f -= f; _edge[e ^ 1].f += f;
            res += f;
            if(res == maxf) break;
        }
    }
    return res;
}

int main(){
    RG int T = Get();
    while(T--){
        n = Get(); m = Get();
        mem(ft, -1); mem(dis, 63); mem(_ft, -1); ans = cnt = 0;
        for(RG int i = 1; i <= m; i++){
            RG int u = Get(), v = Get(), f = Get();
            if(u == v) continue;
            Add(u, v, f);
        }
        RG int S = Get(), T = Get(); cnt = 0;
        SPFA(S, T);
        for(RG int i = 1; i <= n; i++)
            for(RG int e = ft[i]; e != -1; e = edge[e].nt)
                if(dis[i] + edge[e].f == dis[edge[e].to])
                    Add2(i, edge[e].to, 1), Add2(edge[e].to, i, 0);
        while(Bfs(S, T)) ans += Dfs(S, T, INF);
        printf("%d
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cjoieryl/p/8206406.html