#include <stdio.h>
#define maxnum 1000
#define maxint 999999
int dist[maxnum]; //表示当前点到源点的最短路径长度
int prev[maxnum]; //记录当前点的前一个结点
int c[maxnum][maxnum]; //记录图的两点间路径长度
int n,line; //图的结点数和路径数
void Dij(int n,int v,int *dist, int *prev, int c[maxnum][maxnum]) //v代表源点吗?
{
int s[maxnum] = {0};//判断是否已将该点存入到s数组中
int i;
for(i = n;i>=1;i--)
{
dist[i] = c[v][i];//将从源点到i点的初始距离存入数组dist中
s[i] = 0;//初始化为全部没有用过该点
if(dist[i] == 0)//如果源点到该点的距离为无穷大,则该点前面没有连接点
prev[i] = 0;
else
prev[i] = v;
}
dist[v] = 0; //源点到源点的距离初始化为0
s[v] = 1;//把源点存入数组s
//依次将未放入集合s中的节点,取dist【】最小值的节点放进去
//一旦s包含了所有v中顶点,dist就记录了从源点到所有其他顶点之间的最短路径
//注意是从第二个节点开始,第一个结点表示源点
for(i = 2;i<=n;i++)
{
int tmp = 0;
int u = v;
for(int j = n;j>=1;j--) //找出当前未使用的点j的dist【j】最小值
{
if((!s[j]) && dist[j] > tmp)
{
u = j; //u储存当前邻接点中距离最小的点的号码
tmp = dist[j];
}
}
s[u] = 1; //一次for循环结束后,便找出了所有未使用的点中距离最小的点,将此点存入集合s中
//更新dist值
for(int j = n;j>=1;j--)
{
if((!s[j]) && c[u][j]>0) //确定该点没有加入s集合,并且存在这段距离,即经过该点
{
int newdist = dist[u] + c[u][j];//判断经过该点到j的距离和不经过该点到j的距离的大小
if(newdist > dist[j])
{
dist[j] = newdist;
prev[j] = u;
}
}
}
}
}
//查找从源点v到终点u的路径,并输出
void searc(int *prev,int v,int u)
{
int que[maxnum]; //该数组保存路径
int tot = 1;
que[tot] = u; //从终点开始找,一直找到源点v并记录路径
tot++;
int tmp = prev[u];
while(tmp != v)
{
que[tot] = tmp;
tot++;
tmp = prev[tmp];
}
que[tot] = v;
for(int i = tot;i>=1;i--)//输出
{
if(i!=1)
printf("%d->",que[i]);
else
printf("%d\n",que[i]);
}
//注意,若题目要求输出距离,则直接输出dist【u】即可
}
int main()
{
scanf("%d %d",&n,&line);
int p,q,len;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=n;j++)
c[i][j] = 0;
}
for(int i = 1;i<=line;i++)
{
dist[i] = 0;
}
for(int i = 1;i<=line;i++)
{
scanf("%d%d%d",&p,&q,&len);
if(len>c[p][q])
{
c[p][q] = len;
//c[q][p] = len;
}
}
Dij(n,1,dist,prev,c);
printf("从源点到终点的最短路径长度为%d\n",dist[n]);
searc(prev,1,n);
return 0;
}
下面是spfa的方法
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
int u,v,w,next;
} edge[500010];
int cnt,n,m,head[10010],dis[10010],vis[10010],pre[10010], pre1[10005];
int id[10005],cd[10005];
void add(int u,int v,int len)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].w=len;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void spfa(int u,int v,int n)
{
memset(vis,0,sizeof(vis));
memset(pre,INF,sizeof(pre));
memset(dis,-INF,sizeof(dis));
queue<int>q;
q.push(u);
dis[u]=0;
vis[u]=1;
while(!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for(int p=head[x]; p!=-1; p=edge[p].next)
{
if(dis[edge[p].v]<dis[x]+edge[p].w||(dis[edge[p].v]==dis[x]+edge[p].w&&x<pre[edge[p].v]))
{
dis[edge[p].v]=dis[x]+edge[p].w;
pre[edge[p].v]=x;
if(!vis[edge[p].v])
{
vis[edge[p].v]=1;
q.push(edge[p].v);
}
}
}
}
int k=0;
printf("%d\n",dis[v]);
for(int i=v; i!=INF; i=pre[i])
pre1[k++]=i;
for(int i=1; i<k; i++)
printf("%d %d\n",pre1[i-1],pre1[i]);
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
int u,v,w;
memset(head,-1,sizeof(head));
memset(id,0,sizeof(id));
memset(cd,0,sizeof(cd));
while(m--)
{
scanf("%d %d %d",&u,&v,&w);
add(v,u,w);
id[u]++;
cd[v]++;
}
for(int i=1; i<=n; i++)
{
if(id[i]==0)
u=i;
if(cd[i]==0)
v=i;
}
spfa(u,v,n);
}
return 0;
}