ZOJ 2760 How Many Shortest Path(floyd+最大流)

来源:互联网 发布:yum安装软件原理 编辑:程序博客网 时间:2024/06/05 03:13

刚开始还屁颠屁颠的找出最短路,删除所有最短路上的边,然后继续找,WA到死.

看了题解才知道要用最大流,网络流思想很奇妙.

找到最路径中用到的边,将边的容量赋值为1,这么流过去,从起点到终点流这样一条流过去就可以保证为一条最短路径而且没有重复边。

现在的题目转化为找最短路路径中用到边。

这样的边有这样的性质:Path(s,i)+E(i,j)+Path(j,t)==Path(s,t):这样的边E(i,j)就在最短路径上;

通过这样的边的一个最大流,就是最短路径的条数。


#include <iostream>#include <memory.h>#include <queue>#include <cstdio>#define INF 0X6F6F6F6Fusing namespace std;const int maxn = 110;int g[maxn][maxn],dis[maxn][maxn] , c[maxn][maxn], fa[maxn], n, m;void floyd(){for (int i = 0; i < n; ++i){for (int j = 0; j < n; ++j){dis[i][j] = g[i][j];}}for (int k = 0 ; k < n; ++k){for (int i = 0 ; i < n; ++i){for (int j = 0 ; j < n; ++j){if(dis[i][k] != -1 && dis[k][j] != -1 && i != j && i !=k && j !=k){if(dis[i][j] == -1)dis[i][j] = dis[i][k] + dis[k][j];else if(dis[i][j] > dis[i][k] + dis[k][j]){dis[i][j] = dis[i][k] + dis[k][j];}}}}}}void constructGraph(int s, int t){for (int i = 0 ; i < n; ++i){for (int j = 0 ; j < n; ++j){if (g[i][j] != -1 && dis[s][i] != -1 && dis[j][t] != -1 && i != j){if(dis[s][i] + g[i][j] + dis[j][t] == dis[s][t]){c[i][j]++;}}}}}bool bfs(int s, int t){memset(fa, -1, sizeof(fa));queue<int> q;q.push(s);while (q.size()){int u = q.front();q.pop();if(u == t) return true;for (int i = 0 ; i < n; ++i){if (c[u][i] && fa[i] < 0){fa[i] = u;q.push(i);}}}return false;}int EK(int s, int t){int ans = 0;while (bfs(s, t)){for (int i = t; i != s; i = fa[i]){c[fa[i]][i]--;c[i][fa[i]]++;}ans++;}return ans;}int main(){while (scanf("%d", &n) != EOF){memset(c, 0, sizeof(c));for (int i = 0; i < n ; ++i){for (int j = 0; j < n ; ++j){scanf("%d", &g[i][j]);}g[i][i] = 0;}int s, t, minv=0, ans =0;scanf("%d%d", &s, &t);if(s == t){printf("inf\n");continue;}floyd();constructGraph(s, t);printf("%d\n",EK(s, t));}return 0;}