【ZOJ2760】How Many Shortest Path
How Many Shortest Path
标签: 网络流
描述
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.
Sample Input
4
0 1 1 -1
-1 0 1 1
-1 -1 0 1
-1 -1 -1 0
0 3
5
0 1 1 -1 -1
-1 0 1 1 -1
-1 -1 0 1 -1
-1 -1 -1 0 1
-1 -1 -1 -1 0
0 4
Sample Output
2
1
扯淡
看见大佬们都在虐题好紧张啊,于是跑过来被题虐。
题意
给你一张图,求从起点到终点最多有多少条最短路径(互不重合)。
题解
- 本题光凭最短路是无法解决的,我们还需要建立网络流模型来解决。
- 对于每一条边,这些最短路只会经过一次。所以,我们只需要把所有属于最短路上面的边都找出来,在新的网络流模型中连这样一条边。跑一遍网络流,问题就解决了。
- 如何检查边是否在最短路上呢?你先跑一遍最短路,然后对于每一条边,只需要检查dist[起点][i]+a[i][j]+dist[j][终点]是否等于dist[起点][终点]就行了。
PS:
- 自己到自己的边不一定为0......造数据的人怎么想的。
- 我打了两遍这道题,第一遍用spfa写的很丑,还T了,于是又写了一遍floyd,然后......也T了。仔细一看题目发现我很傻逼,没有看到如果起点和终点一样,就输出"inf",然后两份代码改完之后都A了。这说明题目中的细节有时候也是很重要的。
Code
两份代码都粘上来
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
#define ll long long
#define REP(i,a,b) for(register int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(register int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(register int i=start[(a)];i;i=e[i].next)
inline int read()
{
	int sum=0,p=1;char ch=getchar();
	while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
	if(ch=='-')p=-1,ch=getchar();
	while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
	return sum*p;
}
const int maxn=220;
int dist[maxn][maxn],a[maxn][maxn],n;
struct node {
	int v,next,w;
};
node e[maxn*maxn];
int start[maxn],cnt;
void addedge(int u,int v,int w)
{
	e[++cnt]={v,start[u],w};
	start[u]=cnt;
}
void Addedge(int u,int v,int w)
{
	addedge(u,v,w);
	addedge(v,u,0);
}
int st,en,S,T;
bool init()
{
	cnt=1;
	memset(start,0,sizeof(start));
	REP(i,1,n)
	{
		REP(j,1,n)
		{
			dist[i][j]=a[i][j]=read();
			if(a[i][j]==-1)dist[i][j]=a[i][j]=1<<27;
			if(i==j)dist[i][j]=a[i][j]=0;
		}
	}
	REP(k,1,n)
	{
		REP(i,1,n)
		{
			REP(j,1,n)
			{
				dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
			}
		}
	}
	st=read()+1;en=read()+1;
	S=0;T=n+1;
	if(st==en)
	{
		cout<<"inf"<<endl;
		return false;
	}
	Addedge(S,st,1<<30);Addedge(en,T,1<<30);
	REP(i,1,n)
	{
		REP(j,1,n)
		{
			if(i==j)continue;
			if(a[i][j]==(1<<27))continue;
			if(dist[st][en]==dist[st][i]+dist[j][en]+a[i][j])
				Addedge(i,j,1);
		}
	}
	return true;
}
int lev[maxn],cur[maxn];
bool bfs()
{
	queue<int>q;
	REP(i,0,n+1)lev[i]=0;
	q.push(S);
	lev[S]=1;
	do{
		int u=q.front();q.pop();
		EREP(i,u)
		{
			int v=e[i].v;
			if(!lev[v] && e[i].w)
			{
				lev[v]=lev[u]+1;
				q.push(v);
				if(v==T)return true;
			}
		}
	}while(!q.empty());
	return false;
}
int dfs(int u,int flow)
{
	if(u==T)return flow;
	int tag=0;
	for(int &i=cur[u];i;i=e[i].next)
	{
		int v=e[i].v;
		if(lev[v]==lev[u]+1 && e[i].w)
		{
			int c=dfs(v,min(flow-tag,e[i].w));
			e[i].w-=c;
			e[i^1].w+=c;
			tag+=c;
			if(tag==flow)return tag;
		}
	}
	return tag;
}
void doing()
{
	int ans=0;
	while(bfs())
	{
		REP(i,0,n+1)cur[i]=start[i];
		ans+=dfs(S,1<<30);
	}
	cout<<ans<<endl;
}
int main()
{
	while(scanf("%d",&n)==1)
	{
		if(init())
		doing();
	}
	return 0;
}
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
#define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(int i=start[(a)];i;i=e[i].next)
inline int read()
{
	int sum=0,p=1;char ch=getchar();
	while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
	if(ch=='-')p=-1,ch=getchar();
	while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
	return sum*p;
}
int n,S=0,T=0;
const int maxn=500;
struct node {
	int v,next,w;
};
node e[maxn*maxn];
node ee[maxn*maxn];
node eee[maxn*maxn];
int cnt,start[maxn],a[maxn][maxn];
int cntt,startt[maxn];
int cnttt,starttt[maxn];
void addedge(int u,int v,int w)
{
	e[++cnt]={v,start[u],w};
	start[u]=cnt;
}
void addedge1(int u,int v,int w)
{
	ee[++cntt]={v,startt[u],w};
	startt[u]=cntt;
}
void addedge2(int u,int v,int w)
{
	eee[++cnttt]={v,starttt[u],w};
	starttt[u]=cnttt;
}
void Addedge(int u,int v,int w)
{
	addedge(u,v,w);
	addedge(v,u,0);
}
int flag=1;
void init()
{
	flag=1;
	memset(startt,0,sizeof(startt));
	cntt=0;
	cnt=1;
	cnttt=0;
	memset(start,0,sizeof(start));
	memset(starttt,0,sizeof(starttt));
	REP(i,1,n)
	{
		REP(j,1,n)
		{
			a[i][j]=read();
		}
	}
	REP(i,1,n)
	{
		REP(j,i+1,n)
		{
			if(a[i][j]!=-1)addedge1(i,j,a[i][j]),addedge2(j,i,a[i][j]);
			if(a[j][i]!=-1)addedge1(j,i,a[j][i]),addedge2(i,j,a[j][i]);
		}
	}
	S=read()+1,T=read()+1;
	if(S==T)
	{
		cout<<"inf"<<endl;
		flag=0;
	}
	Addedge(0,S,1<<30);
	Addedge(T,n+1,1<<30);
}
int dist[maxn],vis[maxn];
#include<queue>
bool spfa()
{
	REP(i,1,n)dist[i]=1<<30;
	REP(i,1,n)vis[i]=0;
	dist[S]=0;
	vis[S]=1;
	queue<int>q;
	q.push(S);
	do{
		int u=q.front();q.pop();
		//EREP(i,u)
		for(int i=startt[u];i;i=ee[i].next)
		{
			int v=ee[i].v;
			if(dist[v]>dist[u]+ee[i].w)
			{
				dist[v]=dist[u]+ee[i].w;
				if(!vis[v])
				{
					vis[v]=1;
					q.push(v);
				}
			}
		}
		vis[u]=0;
	}while(!q.empty());
	if(dist[T]==(1<<30))return false;
	return true;
}
int dist1[maxn];
void spfa1()
{
	REP(i,1,n)dist1[i]=1<<30;
	REP(i,1,n)vis[i]=0;
	dist1[S]=0;
	vis[S]=1;
	queue<int>q;
	q.push(S);
	do{
		int u=q.front();q.pop();
		for(int i=starttt[u];i;i=eee[i].next)
		{
			int v=eee[i].v;
			if(dist1[v]>dist1[u]+eee[i].w)
			{
				dist1[v]=dist1[u]+eee[i].w;
				if(!vis[v])
				{
					vis[v]=1;
					q.push(v);
				}
			}
		}
		vis[u]=0;
	}while(!q.empty());
}
int lev[maxn],ans;
bool bfs()
{
	queue<int>q;
	REP(i,0,n+1)lev[i]=0;
	lev[S]=1;
	q.push(S);
	do{
		int u=q.front();q.pop();
		EREP(i,u)
		{
			int v=e[i].v;
			if(e[i].w && !lev[v])
			{
				lev[v]=lev[u]+1;
				q.push(v);
				if(v==T)return true;
			}
		}
	}while(!q.empty());
	return false;
}
int cur[maxn];
int dfs(int u,int flow)
{
	int c=0,tag=0;
	if(u==T)return flow;
	for(int &i=cur[u];i;i=e[i].next)
	{
		int v=e[i].v;
		if(e[i].w && lev[v]==lev[u]+1)
		{
			c=dfs(v,min(flow-tag,e[i].w));
			e[i].w-=c;
			e[i^1].w+=c;
			tag+=c;
			if(tag==flow)return tag;
		}
	}
	return tag;
}
void doing()
{
	if(!spfa())
	{
		cout<<"0"<<endl;
		return;
	}
	swap(S,T);
	spfa1();
	swap(S,T);
	REP(i,1,n)
	{
		for(int j=startt[i];j;j=ee[j].next)
		{
			int v=ee[j].v;
			if(dist[i]+ee[j].w+dist1[v]==dist[T])Addedge(i,v,1);
		}
	}
	S=0;T=n+1;
	ans=0;
	while(bfs())
	{
		REP(i,0,n+1)cur[i]=start[i];
		ans+=dfs(S,1<<30);
	}
	cout<<ans<<endl;
}
int main()
{
	while(scanf("%d",&n)==1)
	{
		init();
		if(flag)
		doing();
	}
	return 0;
}
【ZOJ2760】How Many Shortest Path的更多相关文章
- 【CF edu 27 G. Shortest Path Problem?】
		time limit per test 3 seconds memory limit per test 512 megabytes input standard input output standa ... 
- 【Android】 给我一个Path,还你一个酷炫动画
		本篇文章已授权微信公众号 hongyangAndroid (鸿洋)独家公布 转载请标明出处: http://blog.csdn.net/zxt0601/article/details/53040506 ... 
- 【LeetCode】931. Minimum Falling Path Sum 解题报告(Python)
		作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 动态规划 相似题目 参考资料 日期 题目地址:htt ... 
- 【leetcode】Binary Tree Maximum Path Sum
		Binary Tree Maximum Path Sum Given a binary tree, find the maximum path sum. The path may start and ... 
- 【leetcode】Binary Tree Maximum Path Sum  (medium)
		Given a binary tree, find the maximum path sum. The path may start and end at any node in the tree. ... 
- 【iOS】Quartz2D绘图路径Path
		一.绘图路径 A.简单说明 在画线的时候,方法的内部默认创建一个path.它把路径都放到了path里面去. 1.创建路径 cgmutablepathref 调用该方法相当于创建了一个路径,这个路径用 ... 
- 【转】【Mac】invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library
		异常原因 我在昨天升级了 macOX Sierra,悲剧的是,今天我发现git命令无法执行,homebrew也无法使用,这种情景我在升级OS X El Capitan也遇到过一次,完整异常提示如下: ... 
- 【字典树】【树】【二进制】bzoj1954/POJ3764The xor-longest Path 题解
		建立字典树是异或的一种处理方法. Description In an edge-weighted tree, the xor-length of a path p is defined as ... 
- 【转载】SQL Server XML Path
		FOR XML PATH 有的人可能知道有的人可能不知道,其实它就是将查询结果集以XML形式展现,有了它我们可以简化我们的查询语句实现一些以前可能需要借助函数活存储过程来完成的工作.那么以一个实例为主 ... 
随机推荐
- lodash源码分析之缓存使用方式的进一步封装
			在世界上所有的民族之中,支配着他们的喜怒选择的并不是天性,而是他们的观点. --卢梭<社会与契约论> 本文为读 lodash 源码的第九篇,后续文章会更新到这个仓库中,欢迎 star:po ... 
- Thrift之TProtocol系列TJSONProtocol解析
			在了解JSON协议之前,朋友们可以先去了解一下JSON的基础知识,和ASCII基本分布,关于JSON一些常识请见这里; JSON (JavaScript Object Notation)是一种数据交换 ... 
- spring-mvc整合jquery cropper图片裁剪插件
			参考网址:http://blog.csdn.net/u012759397/article/details/53126522 
- python基础7之python3的内置函数
			官方介绍: python3:https://docs.python.org/3/library/functions.html?highlight=built#ascii python2:https:/ ... 
- Socket与ServerSocket
			ServerSocket: 用于打开服务端口,等待客户端连接,运行在服务端. Socket: 用于连接指定服务器的指定端口,运行在客户端. flush是输出到缓冲区,缓冲区没满的话不发送,close的 ... 
- dotnetcore vue+elementUI  前后端分离架二(后端篇)
			前言 最近几年前后端分离架构大行其道,而且各种框架也是层出不穷.本文通过dotnetcore +vue 来介绍 前后端分离架构实战. 涉及的技术栈 服务端技术 mysql 本项目使用mysql 作为持 ... 
- mysql myisam转innodb的2种方法
			mysql myisam转innodb的2种方法 mysql中的myisam和innodb有什么区别.一个好比便利店,一个好比大型购物中心,他们是为了适应不同的场合而存在的.当流量比较小,我们可以 ... 
- ActiveMQ入门练习
			ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久 ... 
- iphone启动图UI切图尺寸对照保存
- Struts2 (一)
			1 三层架构 2 MVC框架的原理 3 什么是Struts2 Struts2是一个非常优秀的MVC框架,基于Model2设计模式. 是由传统的Struts1和WebWork两个经典的框架发展而来的. ... 
