zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ");
                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
    ", G.Maxflow());
        }
    }
    

      

  • 相关阅读:
    二维码生成:使用 JavaScript 库QRCode.js生成二维码
    VC++6.0远程调试(亲试成功)
    Linux同时安装python2和Python3
    Python打包-py2exe
    camera按键采集图像及waitKey的用法(转)
    ucos实时操作系统学习笔记——任务间通信(信号量)(转)
    STM32硬件IIC驱动设计(转)
    基于STM32F4移植W5500官方驱动库ioLibrary_Driver(转)
    USB基础知识概论(版本:v0.9.2)
    usb帧格式
  • 原文地址:https://www.cnblogs.com/oyking/p/3235509.html
Copyright © 2011-2022 走看看