ZOJ 2760 How Many Shortest Path(最短路径+最大流)

Description

Given a weighted directed graph, we define the shortest path as the path who has the smallest length among all the path connecting the source vertex to the target vertex. And if two path is said to be non-overlapping, it means that the two path has no common edge. So, given a weighted directed graph, a source vertex and a target vertex, we are interested in how many non-overlapping shortest path could we find out at most.

Input

Input consists of multiple test cases. The first line of each test case, there is an integer number N (1<=N<=100), which is the number of the vertices. Then follows an N * N matrix, represents the directed graph. Each element of the matrix is either non-negative integer, denotes the length of the edge, or -1, which means there is no edge. At the last, the test case ends with two integer numbers S and T (0<=S, T<=N-1), that is, the starting and ending points. Process to the end of the file.

Output

For each test case, output one line, the number of the the non-overlapping shortest path that we can find at most, or "inf" (without quote), if the starting point meets with the ending.

 

题目大意:一有向有权图,给源点、汇点,问从源点到汇点有多少条不重叠(没有重边)的最短路径

思路:一次floyd,把dis[s][i] + edge[i][j] + dis[j][t] == dis[s][t]的边(最短路径上的边)都加入网络流的图,容量为1。最大流为答案(容量为1,那么这些从源点出发的流都不会有重叠边)。

PS:据说矩阵的对角线上的点不都是0,我把AC代码上的mat[i][i] = st[i][i] = 0注释掉了,果然WA了,这是闹哪样……当然要是你不使用类似于[i][i]这种边就不会有这种烦恼……

 

#include <cstdio>

#include <cstring>

#include <queue>

using namespace std;



const int MAXN = 110;

const int MAXE = MAXN * MAXN * 2;

const int INF = 0x7f7f7f7f;



struct Dinic {

    int n, m, st, ed, ecnt;

    int head[MAXN];

    int cur[MAXN], d[MAXN];

    int to[MAXE], next[MAXE], flow[MAXE], cap[MAXE];



    void init(int ss, int tt, int nn) {

        st = ss; ed = tt; n = nn;

        ecnt = 2;

        memset(head, 0, sizeof(head));

    }



    void add_edge(int u, int v, int c) {

        to[ecnt] = v; cap[ecnt] = c; flow[ecnt] = 0; next[ecnt] = head[u]; head[u] = ecnt++;

        to[ecnt] = u; cap[ecnt] = 0; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++;

    }



    bool bfs() {

        memset(d, 0, sizeof(d));

        queue<int> que; que.push(st);

        d[st] = 1;

        while(!que.empty()) {

            int u = que.front(); que.pop();

            for(int p = head[u]; p; p = next[p]) {

                int v = to[p];

                if(!d[v] && cap[p] > flow[p]) {

                    d[v] = d[u] + 1;

                    que.push(v);

                    if(v == ed) return true;

                }

            }

        }

        return d[ed];

    }



    int dfs(int u, int a) {

        if(u == ed || a == 0) return a;

        int outflow = 0, f;

        for(int &p = cur[u]; p; p = next[p]) {

            int v = to[p];

            if(d[u] + 1 == d[v] && (f = dfs(v, min(a, cap[p] - flow[p]))) > 0) {

                flow[p] += f;

                flow[p ^ 1] -= f;

                outflow += f;

                a -= f;

                if(a == 0) break;

            }

        }

        return outflow;

    }



    int Maxflow() {

        int ans = 0;

        while(bfs()) {

            for(int i = 0; i <= n; ++i) cur[i] = head[i];

            ans += dfs(st, INF);

        }

        return ans;

    }

} G;



int mat[MAXN][MAXN];

int st[MAXN][MAXN];



#define REP(i, t) for(int i = 1; i <= t; ++i)



void floyd(int n) {

    REP(k, n) REP(i, n) REP(j, n) {

        if(st[i][k] == -1 || st[k][j] == -1) continue;

        if(st[i][j] == -1 || st[i][j] > st[i][k] + st[k][j]) st[i][j] = st[i][k] + st[k][j];

    }

    //REP(i, n) REP(j, n) printf("%d\n", st[i][j]);

}



int main() {

    int n, s, t;

    while(scanf("%d", &n) != EOF) {

        REP(i, n) REP(j, n) {

            scanf("%d", &mat[i][j]);

            st[i][j] = mat[i][j];

        }

        REP(i, n) st[i][i] = mat[i][i] = 0;

        scanf("%d%d", &s, &t);

        ++s, ++t;

        if(s == t) {

            printf("inf\n");

            continue;

        }

        floyd(n);

        G.init(s, t, n);

        REP(i, n) REP(j, n)

            if(i != j && mat[i][j] != -1 && st[s][i] != -1 && st[j][t] != -1

               && st[s][t] == st[s][i] + mat[i][j] + st[j][t]) G.add_edge(i, j, 1);

        printf("%d\n", G.Maxflow());

    }

}

  

你可能感兴趣的:(Path)