最短路径问题
最短路径:
一张图中节点到节点之间所经过的边权和最小的路径,称为,之间的最短路径
具体包括下几种类型:
- 确定起点的最短路问题
- 确定终点的最短路问题
- 确定起点和终点的最短路问题
- 全局最短路问题
常见的解决算法有:
- 算法
- 算法
- 算法
算法
多源最短路问题:
给出描述图的邻接矩阵,其中第行第列的元素[][]代表从第个点到第个点有一条长度为[][]的有向边,算法用来计算任意两点之间的最短路
算法描述:
算法的本质是动态规划
设[][][]代表只经过前个点的从到的最短路径,那么[][ ][ ]就是矩阵[ ][ ],对于点对(,)更新到第个点的时候,(,)的最短路径只有两种,一种是经过的,一种是没有经过的,也就是[][][]{[][][],[][][]+[][][]}。
这样的时间复杂度和空间复杂度都是(),但是我们仔细观察就可以发现,其实三维数组的第一维是没有用的,每一次的更新只是使用第层来更新第层,并且最后我们所使用的也只是第层,所以我们没有必要存储所有的数据,也就是可以简化成[][]={[][]+[][],[][]},最终的空间复杂度可以降为()的
细节描述:
在知乎上有一个问题叫做“为什么算法中应该放在循环的最外层”。我们要理解算法的本质是动态规划,在某种意义上是一个时间戳,我们使用第层的数据来更新第层的数据,所以我们必须保证,更新第层的时候,层的数据已经是最优的。
经典题目:
题意:
每个经纪人有个经纪人朋友,给出每个经纪人向其他经纪人传递信息的时间,经纪人向经纪人传递信息的时间不一定相同,给出所有信息之后,询问从某个经纪人出发,把消息传递给所有经纪人的最小时间,输出这个经纪人的序号,如果有一个或者一个以上的经纪人无法接收信息,输出""
题解:
找到所有点对之间的最短路径
代码实现:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=100+5;
int n,dis[maxn][maxn];
inline int read(void){
char ch=getchar();
int f=1,x=0;
while(!(ch>='0'&&ch<='9')){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
x=x*10+ch-'0',ch=getchar();
return f*x;
}
signed main(void){
while(n=read()){
memset(dis,inf,sizeof(dis));
for(int i=1,m,x;i<=n;i++){
m=read();
for(int j=1;j<=m;j++)
x=read(),dis[i][j]=read();
}
for(int i=1;i<=n;i++)
dis[i][i]=0;
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
int ans=inf,node;
for(int i=1;i<=n;i++){
int Max=0;
for(int j=1;j<=n;j++)
Max=max(Max,dis[i][j]);
if(ans>Max)
ans=Max,node=i;
}
if(ans==inf)
cout<<"disjoint"<<endl;
else
cout<<node<<" "<<ans<<endl;
}
return 0;
}
传递闭包问题
问题描述:
求一张图中所有点对之间的路径互达问题
Floyd算法的应用:
我们可以把所有没有直接路径相连的点对之间的边权设为,其他有直接路径相连的点对之间的边权设为,那么如果最终两个节点之间的最短路径为,就代表其之间不可互达
代码实现:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=100+5;
int n,m,mp[maxn][maxn],cnt[maxn],ans;
signed main(void){
memset(mp,0,sizeof(mp)),ans=0,memset(cnt,0,sizeof(cnt));
scanf("%d%d",&n,&m);
for(int i=1,x,y;i<=m;i++)
scanf("%d%d",&x,&y),mp[x][y]=1;
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mp[i][k]&&mp[k][j])
mp[i][j]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mp[i][j]||mp[j][i])
cnt[i]++;
for(int i=1;i<=n;i++)
if(cnt[i]==n-1)
ans++;
cout<<ans<<endl;
return 0;
}
共同学习,写下你的评论
评论加载中...
作者其他优质文章