HDU3416 最短路+最大流

http://acm.hdu.edu.cn/showproblem.php?pid=3416

题意:
有向图求没有交集的A到B最短路的数量
 
很显然要先将所有最短路上的边取出来。
用正向跑一遍dis1,反向跑一遍dis2的方法
dis1[u] + dis2[v] + w == dis1[B]的边就是最短路上的边
但是要求没有交集的最短路,想到最大流,每一条最短路上的边都看作一条流量为1的边,直接跑最大流即可。
 
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d
", x)
#define Prl(x) printf("%lld
",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
#define Vec Point
typedef vector<int> VI;
const double eps = 1e-9;
const int maxn = 2010;
const int maxm = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,tmp,K;
int A,B;
int dis[maxn],dis1[maxn],dis2[maxn];
struct Edge{
    int v,dis,next,flag;
}edge[maxm * 2];
int head[maxn],cnt; 
int head2[maxn],tot;
bool vis[maxn];
struct Edge2{
    int to,next,cap,flow;
}edge2[maxm];
void init(){
    Mem(head,0);
    cnt = 0;
    tot = 2;
    Mem(head2,-1);
}
void addedge(int u,int v,int w,int rw = 0){
    edge2[tot].to = v; edge2[tot].cap = w; edge2[tot].flow = 0;
    edge2[tot].next = head2[u]; head2[u] = tot++;
    edge2[tot].to = u; edge2[tot].cap = rw; edge2[tot].flow = 0;
    edge2[tot].next = head2[v]; head2[v] = tot++;
}
int q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n){
    int front = 0,tail = 0;
    Mem(dep,-1);
    dep[s] = 0;
    q[tail++] = s;
    while(front < tail){
        int u = q[front++];
        for(int i = head2[u]; i != -1; i = edge2[i].next){
            int v = edge2[i].to;
            if(edge2[i].cap > edge2[i].flow && dep[v] == -1){
                dep[v] = dep[u] + 1;
                if(v == t) return true;
                q[tail++] = v;
            }
        }
    }
    return false;
}
int dinic(int s,int t,int n){
    int maxflow = 0;
    while(bfs(s,t,n)){
        for(int i = 1; i <= n ; i ++) cur[i] = head2[i];
        int u = s,tail = 0;
        while(cur[s] != -1){
            if(u == t){
                int tp = INF;
                for(int i = tail - 1; i >= 0; i --){
                    tp = min(tp,edge2[sta[i]].cap - edge2[sta[i]].flow);
                }
                maxflow += tp;
                for(int i = tail - 1; i >= 0 ; i --){
                    edge2[sta[i]].flow += tp;
                    edge2[sta[i] ^ 1].flow -= tp;
                    if(edge2[sta[i]].cap - edge2[sta[i]].flow == 0)
                        tail = i;
                }
                u = edge2[sta[tail] ^ 1].to;
            }else if(cur[u] != -1 && edge2[cur[u]].cap > edge2[cur[u]].flow && dep[u] + 1 == dep[edge2[cur[u]].to]){
                sta[tail++] = cur[u];
                u = edge2[cur[u]].to;
            }else{
                while(u != s && cur[u] == -1){
                    u = edge2[sta[--tail] ^ 1].to;
                }
                cur[u] = edge2[cur[u]].next;
            }
        }
    }
    return maxflow;
}
void add(int u,int v,int w,int flag){
    edge[++cnt].dis = w;
    edge[cnt].v = v;
    edge[cnt].flag = flag;
    edge[cnt].next = head[u];
    head[u] = cnt;
}
struct cmp{
    bool operator () (int a,int b){
        return dis[a] > dis[b];
    }
};
void Dijkstra(int s){
    For(i,1,N) vis[i] = 0,dis[i] = INF;
    dis[s] = 0;
    priority_queue<int,vector<int>,cmp>Q;
    Q.push(s);
    while(!Q.empty()){
        int u = Q.top(); Q.pop();
        if(vis[u]) continue;
        vis[u] = 1;
        for(int i = head[u]; i ; i = edge[i].next){
            int v = edge[i].v; int w = edge[i].dis;
            if(s == A && edge[i].flag == -1 || s == B && edge[i].flag == 1) continue;
            if(!vis[v] && dis[u] + w < dis[v]){
                dis[v] = dis[u] + w;
                Q.push(v);
            }
        }
    }
}
int main()
{
    int T; Sca(T);
    while(T--){
        scanf("%d%d",&N,&M);
        init();
        For(i,1,M){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w,1);
            add(v,u,w,-1);
        }
        scanf("%d%d",&A,&B);
        Dijkstra(A);For(i,1,N) dis1[i] = dis[i];
        Dijkstra(B);For(i,1,N) dis2[i] = dis[i];
        For(i,1,N){
            for(int j = head[i]; j ; j = edge[j].next){
                int v = edge[j].v,w = edge[j].dis;
                if(dis1[i] + dis2[v] + w == dis1[B] && edge[j].flag == 1){
                    addedge(i,v,1);
                }
            }
        }
        Pri(dinic(A,B,N));
    }
    #ifdef VSCode
    system("pause");
    #endif
    return 0;
}
原文地址:https://www.cnblogs.com/Hugh-Locke/p/9553233.html