#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<math.h>
#define inf 0x3f3f3f;
using namespace std;
int n,w[1001][1001],m,a,b,qy,d[1001],t,mx,lj;
bool vis[1001][1001],q[1001];
int main()
{
while(scanf("%d",&m)!=EOF)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
d[i]=inf; q[i]=1; vis[i][i]=0;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
if(vis[a][b]==0)
{
scanf("%d",&lj);
w[a][b]=lj; w[b][a]=lj;
}
else
{
scanf("%d",&lj);
if(lj<w[a][b]) {w[a][b]=lj; w[b][a]=lj;}
}
vis[a][b]=1;
vis[b][a]=1;
}
d[1]=0; qy=1; t=1; q[1]=0;
while(qy)
{
for(int i=1;i<=n;i++)
{
if(vis[t][i]==1)
{
if(d[i]>d[t]+w[t][i])
d[i]=d[t]+w[t][i];
}
}
mx=inf;
for(int i=1;i<=n;i++)
{
if(q[i]==1&&d[i]<mx)
{
mx=d[i];
t=i;
}
}
q[t]=0;
if(t==n)qy=0;
}
printf("%d\n",d[n]);
}
return 0;
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<math.h>
#define inf 0x3f3f3f;
using namespace std;
int n,w[1001][1001],m,a,b,qy,d[1001],t,mx,lj;
bool vis[1001][1001],q[1001];
int main()
{
while(scanf("%d",&m)!=EOF)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
d[i]=inf; q[i]=1; vis[i][i]=0;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
if(vis[a][b]==0)
{
scanf("%d",&lj);
w[a][b]=lj; w[b][a]=lj;
}
else
{
scanf("%d",&lj);
if(lj<w[a][b]) {w[a][b]=lj; w[b][a]=lj;}
}
vis[a][b]=1;
vis[b][a]=1;
}
d[1]=0; qy=1; t=1; q[1]=0;
while(qy)
{
for(int i=1;i<=n;i++)
{
if(vis[t][i]==1)
{
if(d[i]>d[t]+w[t][i])
d[i]=d[t]+w[t][i];
}
}
mx=inf;
for(int i=1;i<=n;i++)
{
if(q[i]==1&&d[i]<mx)
{
mx=d[i];
t=i;
}
}
q[t]=0;
if(t==n)qy=0;
}
printf("%d\n",d[n]);
}
return 0;
}
第一个dijkstra算法的题目,从昨天晚上一直WA到今天下午,蛋疼的说。
主要错的地方是把PPT上面的压缩到S集合中的点U理解错了,理解成和prim算法中一样的U是在S集合外面到S集合最近的点。
U应该是到起点最近的那个点,即式子中的if(q[i]==1&&d[i]<mx)
{mx=d[i];U=i;}
这样做虽然是贪心,但是PPT上面已证这样得到的结果一定是最优的,同时PPT上面还有一句话重要,就是说,每个点必定只会被从Q中弹出进入S中一次且仅有一次。