dijkstra算法 之 畅通工程续(图论)

先介绍一下dijkstra(迪杰斯特拉)算法:

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。(等会儿解释为什么存在负权边)

其基本思想是:设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。


                                                                     dijkstra算法 之 畅通工程续(图论)_第1张图片

举个栗子:输入n,.m分别代表点的个数和边的个数,随后输入m行,每行三个数分别代表两个的位置和权重,最后一行输入两个数,代表起始点和终点,计算从起始点到终点的最短距离

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define INF 99999
const int maxn=100;
int dist[maxn],pre[maxn],graph[maxn][maxn],vis[maxn],n,line;
int dijkstra(int from,int to){
    for(int i=1;i<=n;i++){
        vis[i]=0;         //每个点开始都设置为未访问
        dist[i]=graph[from][i];   //dist表示某点到from的距离
        if(dist[i]==INF)pre[i]=-1;
        else pre[i]=from;   //记录与from相连的点
    }
    dist[from]=0;   //到自身的距离为0
    vis[from]=1;  //起始点标记为访问过
    for(int i=1;i<=n;i++){  
        int minn=INF,pos;
        for(int j=1;j<=n;j++){   //搜索到基准点最近的点
            if(!vis[j]&&minn>dist[j]){
                minn=dist[j];  //记录最小的距离
                pos=j;  //标记位置
            }
        }
        vis[pos]=1;  //找到了离基准点最近的点,则将它也设置为访问过
        for(int j=1;j<=n;j++){  //以刚找的点为准向外扩展 更新dist
            if(!vis[j]&&(dist[j]>dist[pos]+graph[pos][j])){  //如果某点到起始点的距离大于pos这个点到起始点的距离加
                                                             //上某点到pos这点距离,则更新。相当于是比较某点到起始点的距离和
                                                             //某点经过其他点再到起始点距离大小
                dist[j]=dist[pos]+graph[pos][j];
                pre[j]=pos;    //某点是从pos这点“走”过来的
            }
        }
    }
    return dist[to];
} 
void print(int to)            //打印路径
{
    if(to==-1)return;
    print(pre[to]);
    printf("%d ",to);
}
int main()
{
    scanf("%d%d",&n,&line);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)    //任意两点之间的距离定义为一个极大值
           graph[i][j]=INF;
    int p,q,len;
    for(int i=1;i<=line;i++){
        scanf("%d%d%d",&p,&q,&len);
        if(len
如果存在负权边,则dist最小为负无穷了,因为我可以一直沿着某个环走,越走越小。所以不能有负权边。


经典的最简单最短路径的题目:HDU 畅通工程续(套模板就行了...)http://acm.hdu.edu.cn/showproblem.php?pid=1874

某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。

现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
Input
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0 接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B 再接下一行有两个整数S,T(0<=S,T Output
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
Sample Input
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2
Sample Output
2
-1

AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define INF 999999
const int maxn=210;
int n,m,mapp[maxn][maxn],dist[maxn],pre[maxn];

void dijkstra(int from,int to){
    bool s[maxn];
    for(int i=0;i





你可能感兴趣的:(dijkstra算法 之 畅通工程续(图论))