用
init()子函数来初始化各种数据
,
包括节点与节点之间未连通状态时权值为INF(除了相同的节点)
,
以及每个节点初始化权值为INF(除了第一个节点),
还有就是标记数组,说明都还未被访问过。
用digkstra子函数用了三个for循环
,
最外层循环是为了遍历全部的节点,使他们的权值都改变为从一节点到他们各自最小的总权值
,
第二层循环是为了不断更新未访问的点(最近的优先,所以就有了其中的m=INF,是为了得到一个节点周边最小的权值),
第三层就是更新最小的权值,比如节点A--->节点B--->节点C权值为10,但是节点A--->节点C的权值为5,所以就要更新。
然后就是主函数,输入数据可能会有边的重复
,所以就要判断一下,如果这两个点未曾连通,那就直接赋值(因为是无向图),如果存在值,那就要比较一下,取最小的赋值给它。
下面是具体代码:
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<iostream>
#define INF (1<<30)-1
using namespace std;
int n,t;
int w[1005][1005];
int v[1005],d[1005];
void init()
{
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
w[i][j]=(i==j?0:INF);
memset(v,0,sizeof(v));
d[1]=0;
for(i=2;i<=n;i++)
d[i]=INF;
}
void digkstra()
{
int i,j,m,x;
for(i=1;i<=n;i++)
{
m=INF;
for(j=1;j<=n;j++)
{
if(!v[j]&&d[j]<=m)
m=d[x=j];
}
v[x]=1;
for(j=1;j<=n;j++)
{
if(d[j]>d[x]+w[j][x])
d[j]=d[x]+w[j][x];
}
}
cout<<d[n]<<endl;
}
int main()
{
while(~scanf("%d%d",&t,&n))
{
init();
int y,z,p;
for(int i=0;i<t;i++)
{
scanf("%d%d",&y,&z);
if(w[y][z]==INF&&w[z][y]==INF)
{
scanf("%d",&w[y][z]);
w[z][y]=w[y][z];
}
else
{
scanf("%d",&p);
if(p<min(w[z][y],w[y][z]))
{
w[z][y]=p;
w[y][z]=p;
}
}
}
digkstra();
}
return 0;
}
下面这一种使用了队列(不是优先队列),即是 spfa算法 ,思路是把每一个权值更新的点依次压进队列里,可以手动模拟其过程,会发现还是按着一个点开始,往周围散发。
代码如下:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<queue>
#define INF (1<<30)-1
using namespace std;
int t,n;
int w[1005][1005],d[1005];
bool v[1005];
void spfa()
{
int i,j;
queue<int> q;
q.push(1);
v[1]=1;
while(!q.empty())
{
int x=q.front();
q.pop();
v[x]=0;
for(i=1; i<=n; i++)
{
if(d[i]>d[x]+w[i][x])
{
d[i]=d[x]+w[i][x];
if(!v[i])
q.push(i),
v[i]=1;
}
}
}
printf("%d\n",d[n]);
}
int main()
{
while(~scanf("%d%d",&t,&n))
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
w[i][j]=(i==j?0:INF);
for(int i=1; i<=n; i++)
d[i]=(i==1?0:INF);
memset(v,0,sizeof(v));
int x,y,z;
for(int i=0; i<t; i++)
{
scanf("%d%d%d",&x,&y,&z);
w[x][y]=w[y][x]=min(w[x][y],min(w[x][y],z));
}
spfa();
}
}