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());
        }
    }
    

      

  • 相关阅读:
    面向对象之设计模式大全
    JDK各版本新增的主要特性
    迷宫最短路径-货郎担问题的解决思路
    详细介绍Java垃圾回收机制
    并发编程与任务建模
    淘宝npm镜像使用方法
    Metrics-Java版的指标度量工具
    Velocity基本语法
    Git之”make sure you have the correct access…”
    Mysql的转义字符
  • 原文地址:https://www.cnblogs.com/oyking/p/3235509.html
Copyright © 2011-2022 走看看