HDU3416 Marriage Match IV

给一个带权有向图,两个点AB,求A到B有几条最短路,每条边只能走以次!
先跑两边Dij,求出A到各个点的最短路和各个点到B的最短路,后者是先反向建边在跑Dij就行,然后枚举边,若满足dist1[from]+e[i].weight+dist[to] == dist1[B],则说明所有的最短路中包含此条边,找到所有的这样的边,然后在这些边上跑网络流,每条边的流量设置为1,最后跑出来的结果就是答案。

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 1005, maxm = 1e5+5;
struct node{
    int pos, dist;
    node(int a, int b): pos(a), dist(b){}
    friend bool operator < (const struct node &a, const struct node &b){
        return a.dist > b.dist;
    }
};
struct edge{
    int from, to, dist, next;
}e[maxm*2];
int n, m, tot, A, B;
int head[maxn], vis[maxn], dist1[maxn], dist2[maxn];

struct Edge{
    int from, to, c, f;
    Edge(int a, int b, int e, int d): from(a), to(b), c(e), f(d){}
};

int cnt, depth[maxn], cur[maxn];
vector<Edge> E;
vector<int> G[maxn];

inline bool BFS(int s, int t){
    for (int i=1; i<=n; i++)    depth[i] = 0;
    depth[s] = 1;
    queue<int> q;
    q.push(s);
    while (!q.empty()){
        int tmp = q.front();    q.pop();
        for (int i=0; i<G[tmp].size(); i++){
            Edge& e = E[G[tmp][i]];
            if (e.c>e.f && !depth[e.to]){
                depth[e.to] = depth[tmp] + 1;
                q.push(e.to);
            }
        }
    }
    return depth[t];
}

inline int DFS(int s, int t, int flow){
    if (s==t || flow<=0)    return flow;
    int rest = flow;
    for (int &i=cur[s]; i<G[s].size(); i++)  if (depth[E[G[s][i]].to]==depth[s]+1 && E[G[s][i]].c>E[G[s][i]].f){
        int tmp = DFS(E[G[s][i]].to, t, min(rest, E[G[s][i]].c-E[G[s][i]].f));
        if (tmp<=0) depth[E[G[s][i]].to] = 0;
        rest -= tmp;
        E[G[s][i]].f += tmp;
        E[G[s][i]^1].f -= tmp;
        if (rest==0)    break;
    }
    return flow - rest;
}

int DINIC(int s, int t){
    int ans = 0;
    while (BFS(s, t)){
        ans += DFS(s, t, 9999999);
        for (int i=1; i<=n; i++)    cur[i] = 0;
    }
    return ans;
}

inline void Add(int from, int to, int cap){
    E.push_back(Edge(from, to, cap, 0));
    E.push_back(Edge(to, from, 0, 0));
    cnt += 2;
    G[from].push_back(cnt-2);
    G[to].push_back(cnt-1);
    return;
}

void Dijkstra(int s, int dist[]){
    for (int i=1; i<=n; i++)    vis[i] = 0, dist[i] = 999999999;
    priority_queue<node> q;
    dist[s] = 0;
    q.push(node(s, 0));
    while (!q.empty()){
        node tmp = q.top();    q.pop();
        if (vis[tmp.pos])   continue;
        vis[tmp.pos] = 1;
        for (int i=head[tmp.pos]; i; i=e[i].next)   if (dist[e[i].to] > tmp.dist+e[i].dist){
            dist[e[i].to] = tmp.dist+e[i].dist;
            q.push(node(e[i].to, dist[e[i].to]));
        }
    }
    return;
}

inline void add(int from, int to, int dist){
    tot++;
    e[tot].from = from, e[tot].to = to, e[tot].dist = dist, e[tot].next = head[from];
    head[from] = tot;
    return;
}
inline int read(){
    int x=0;    char ch=getchar();
    while (ch<'0' || ch>'9')    ch=getchar();
    while (ch>='0' && ch<='9'){
        x = x*10 + ch-'0';
        ch=getchar();
    }
    return x;
}

int main(){
    int t = read(), from, to, w;
    while (t--){
        n = read(), m = read(), tot = cnt = 0;
        for (int i=1; i<=n; i++)    head[i] = 0;
        E.clear();
        for (int i=1; i<=n; i++)    G[i].clear();
        for (int i=1; i<=m; i++){
            from = read(), to = read(), w = read();
            add(from, to, w);
        }
        A = read(), B = read();
        Dijkstra(A, dist1);
        for (int j=1; j<=2; j++){
            for (int i=1; i<=n; i++)    head[i] = 0;
            for (int i=1; i<=tot; i++){
                int tmp = e[i].from;
                e[i].from = e[i].to;
                e[i].to = tmp;
                e[i].next = head[e[i].from];
                head[e[i].from] = i;
            }
            if (j==1)   Dijkstra(B, dist2);
        }
        for (int i=1; i<=tot; i++)  if (dist1[e[i].from]+e[i].dist+dist2[e[i].to] == dist1[B]){
            Add(e[i].from, e[i].to, 1);
        }
        printf ("%d\n", DINIC(A, B));
    }
    return 0;
}
分类: 网络流

0 条评论

发表评论

邮箱地址不会被公开。