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

      

  • 相关阅读:
    jemeter使用笔记
    webtest mobile + Android / Battery Historian / SoloPi
    script / go / golang
    my live house / air conditioning / dajin / dakin / FTXG50JV2CW
    OS + Centos OS 8 Thinkpad TrackPoint
    network router Gpon
    Mybatisplus 自定义sql 使用条件构造器 多表查询分页
    处理fastJson 序列化时间问题
    js 实现轮播图 超级简单 组件已封装
    Webpack-dev-server的proxy用法
  • 原文地址:https://www.cnblogs.com/oyking/p/3235509.html
Copyright © 2011-2022 走看看