题目描述
一个含n个结点的无向图,以矩阵存储方式给出,请求出指定的两个点之间的最短距离。
输入格式:
第一行,一个整数n(0 < n < 1000 ),表示无向图中结点的个数。
接下来是一个n*n的矩阵,表示无向图中各结点之间的联结情况,矩阵中的数值为小于等于1000的下整数,其中 0 表示两点之间无直接连接。
最后一行,两个整数i,j。表示求解i点到j点的最短距离。
输出格式:
一个数值,表示指定的两点之间最短距离。
输入样例#1:
2
0 2
2 0
1 2
输出样例#1:
2
【解题分析】
这是比较直白的一个单源点最短路问题,使用dijkstra算法,给每个节点设置标号,dis[i]表示从源点到第i个点的最短路的值,每次从还没标记的点里面找一个最小的dis值,将它标记掉(即确认该点的dis为它最短路),然后将这个点的所有有关联的点的dis进行更新,直到全部点处理完成。过程有点像贪心,每次取最小dis的值,但是需要不断的利用最新确定的点的dis值去更新其他点的dis值,对于所有边都是大于0的情况,这是必然可行的,这个更新的过程本质上是个DP的过程。
如果边权有负数呢?这个正确性就无法保证了,所以dijkstra算法只对正权边图有效。
进一步的,改算法的过程具有贪心性,每次取最小的dis,我们可以使用优先队列(二叉堆)对它 进行优化,提高它的运行效率。
【参考代码】
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef pair<int,int> PP;
const int nn=10005;
struct aty{
int next,to,w;
}edge[nn];
int n,d[nn],head[nn],cnt=1,x,s,t;
void add(int u,int v,int w){
edge[cnt].next=head[u];
edge[cnt].to=v;
edge[cnt].w=w;
head[u]=cnt++;
}
void dijkstra(int s){
priority_queue<PP,vector<PP>,greater<PP> > p;
memset(d,0x3f,sizeof(d));
d[s]=0;
p.push(PP(0,s));
while(!p.empty()){
PP q=p.top();
p.pop();
int u=q.second;
if(d[u]<q.first) continue;
if(u==t) break;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(d[v]>d[u]+edge[i].w)
d[v]=d[u]+edge[i].w,
p.push(PP(d[v],v));
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
cin>>x;
if(x)add(i,j,x);
}
cin>>s>>t;
dijkstra(s);
cout<<d[t];
return 0;
}版权声明:本文为snail2035原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。