// Dijikstra.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#define INF 10000000
int dis[505][505];
int co[505][505];
int main()
{
int n, m, s, d;
scanf("%d %d %d %d",&n,&m,&s,&d);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
dis[i][j] = INF;
co[i][j] = INF;
}
}
int c1, c2, distance, cost;
for (int i = 0; i < m; i++)
{
scanf("%d %d %d %d",&c1,&c2,&distance,&cost);
dis[c1][c2] = distance;
dis[c2][c1] = distance;
co[c1][c2] = cost;
co[c2][c1] = cost;
}
int flag[505] = { 0 };
int path[505] = {-1};
for (int i = 0; i<n; i++)
{
if (dis[s][i]<INF)
path[i] = s;
else
path[i] = -1;
}
flag[s] = 1;
int min;
for (int i = 0; i < n; i++)
{
int dmin = INF;
for(int j=0;j<n;j++)
{
if (flag[j] == 0 && dis[s][j] < dmin)
{
dmin = dis[s][j];
min = j;
}
}
flag[min] = 1;
if (min == d)
{
//break;
}
for (int j = 0; j < n; j++)
{
distance = dis[s][min] + dis[min][j];
cost = co[s][min] + co[min][j];
if (flag[j] == 0 && dis[s][j] > distance)
{
dis[s][j] = distance;
co[s][j] = cost;
path[j] = min;
}
else if(flag[j]==0&&dis[s][j]==distance&&co[s][j]>cost)
{
dis[s][j] = distance;
co[s][j] = cost;
path[j] = min;
}
}
}
int k = d;
int temp[505];
int i = n-1;
temp[i] = k;
while (path[k] != -1)
{
temp[--i] = path[k];
k = path[k];
}
for (i; i < n; i++)
{
printf("%d ",temp[i]);
}
printf("%d %d",dis[s][d],co[s][d]);
scanf("%d", &n);
return 0;
}
思路找出距离起点最近的点,然后用该点更新所有点到出发点距离,然后将该点标记为已读
再在剩下点里找最近的点,然后更新其他所有点(除了已读的点)通过该点到达起始点的距离
以此类推,一直到找最近的点找到重点
这就利用了贪心,每次找局部最优点。
证明:为什么每次找到的最小点就一定是最小点
因为找到的第一个最小点是与起点直相连的边最短的点,
找到的第二个点,如果不是与起点直接相连,且与起点直接相连的点并未全部标记为已读,则证明与起点直接相连的其他点的边都大于,起点到第一个最小点的边加上第一个最小点到第二个最小点的边的和,则第二个最小点是不可能通过其他点到达起点的边的和更小,一次类推,每次找到的最小点就是最小点。
写的并不是很好,因为没有图,如果看不懂的可以留言问