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

      

  • 相关阅读:
    sqlserver 脚本生成数据库文档
    在命令行中执行kms命令激活Microsoft Office 2010
    .NET Core项目修改project.json来引用其他目录下的源码等文件的办法 & 解决多框架时 project.json 与 app.config冲突的问题
    asp.net 访问局域网共享文件
    Winform开发框架的重要特性总结
    Winform开发框架之插件化应用框架实现
    Winform开发框架之权限管理系统的改进
    Winform开发框架之统计图表的实现
    在Winform开发框架中实现对数据库的加密支持
    Winform开发框架之通用高级查询模块
  • 原文地址:https://www.cnblogs.com/oyking/p/3235509.html
Copyright © 2020-2023  润新知