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

  

ZOJ 2760 How Many Shortest Path(最短路径+最大流)的更多相关文章

  1. zoj 2760 How Many Shortest Path【最大流】

    不重叠最短路计数. 先弗洛伊德求一遍两两距离(其实spfa或者迪杰斯特拉会更快但是没必要懒得写),然后设dis为st最短距离,把满足a[s][u]+b[u][v]+a[v][t]==dis的边(u,v ...

  2. zoj 2760 How Many Shortest Path 最大流

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760 Given a weighted directed graph ...

  3. ZOJ 2760 - How Many Shortest Path - [spfa最短路][最大流建图]

    人老了就比较懒,故意挑了到看起来很和蔼的题目做,然后套个spfa和dinic的模板WA了5发,人老了,可能不适合这种刺激的竞技运动了…… 题目链接:http://acm.zju.edu.cn/onli ...

  4. ZOJ 2760 How Many Shortest Path (不相交的最短路径个数)

    [题意]给定一个N(N<=100)个节点的有向图,求不相交的最短路径个数(两条路径没有公共边). [思路]先用Floyd求出最短路,把最短路上的边加到网络流中,这样就保证了从s->t的一个 ...

  5. ZOJ 2760 How Many Shortest Path

    题目大意:给定一个带权有向图G=(V, E)和源点s.汇点t,问s-t边不相交最短路最多有几条.(1 <= N <= 100) 题解:从源点汇点各跑一次Dij,然后对于每一条边(u,v)如 ...

  6. ZOJ 2760 How Many Shortest Path(Dijistra + ISAP 最大流)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760 题意:给定一个带权有向图 G=(V, E)和源点 s.汇点 t ...

  7. SPOJ 15. The Shortest Path 最短路径题解

    本题就是给出一组cities.然后以下会询问,两个cities之间的最短路径. 属于反复询问的问题,临时我仅仅想到使用Dijsktra+heap实现了. 由于本题反复查询次数也不多,故此假设保存全部最 ...

  8. [ZOJ2760]How Many Shortest Path(floyd+最大流)

    题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760 题意:给你一个一个n*n(n<=100)的有向图,问你从s到 ...

  9. [Swift]LeetCode847. 访问所有节点的最短路径 | Shortest Path Visiting All Nodes

    An undirected, connected graph of N nodes (labeled 0, 1, 2, ..., N-1) is given as graph. graph.lengt ...

随机推荐

  1. 个人免签收款接口 bufpay.com 支持限额设置

    有产品希望收款分布到不同的手机,每个当手机达到某一限额以后就停止改手机的收款. bufpay.com 近期上线了收款限额设置功能,配置界面如下图: 每个手机微信或支付宝可以单独设置每日限额,如果该手机 ...

  2. Java之变量

    Java变量分为类变量.实例变量.局部变量: 类变量包括静态变量: 局部变量:就是本地变量,使用范围:方法,构造器(构造方法),块:销毁:程序执行完或退出立即销毁:局部变量没有默认值,声明的同时必须赋 ...

  3. springboot-redis缓存

    Redis缓存使用 1.  引入依赖(可能已经引入了):spring-boot-starter-cache 2.  在application.yml配置文件中配置spring:redis:host/p ...

  4. mysql 的基本操作总结--增删改查

    本文只是总结一下mysql 的基本操作,增删改查,以便忘记的时候可以查询一下 1.创建数据库 语法:CREATE DATABASES 数据库名; 例子: CREATE DATABASES studen ...

  5. Python豆瓣源

    pip install -i https://pypi.doubanio.com/simple/ xxxx

  6. Mongodb从库配置

    1. 先以master方式启动mongodb 2. 导入主库的数据文件:/data/mongodb-3.0.12/bin/mongorestore /data/tmp/mongodbbak/ 3. 关 ...

  7. 基于C语言的面向对象编程

    嵌入式软件开发中,虽然很多的开发工具已经支持C++的开发,但是因为有时考虑运行效率和编程习惯,还是有很多人喜欢用C来开发嵌入式软件.Miro Samek说:"我在开发现场发现,很多嵌入式软件 ...

  8. C语言经典程序100例

    -------------------------------------------------------------------------------- [程序1] 题目:古典问题:有一对兔子 ...

  9. linux下Intellij Idea 14的安装

    一.安装配置jdk                                                         虽然很多Linux发行版现在已经自带OpenJDK,但是在开发过程中 ...

  10. ubuntu16安装过程中的硬盘分区

    硬盘分区主要是三个区,如下图,分别是/,swap交换空间,/home,其中第一个分区/是主分区,建议至少8GB,要不ubuntu安装的时候放不下.