zoukankan      html  css  js  c++  java
  • 【图算法】Dijkstra算法及变形

    图示:

    无向图

    模版:

      1 /*
      2 Dijkstra计算单源最短路径,并记录路径
      3 
      4 m个点,n条边,每条边上的权值非负,求起点st到终点et的最短路径
      5 
      6 input:
      7 n m st et
      8 6 10 1 6            
      9 1 2 6
     10 1 3 2
     11 1 4 1
     12 2 3 6
     13 2 5 3
     14 3 4 2
     15 3 5 2
     16 3 6 4
     17 4 6 5
     18 5 6 3
     19 
     20 output:
     21 6
     22 1-->4-->6
     23 */
     24 
     25 
     26 
     27 #include<iostream>
     28 #include<stdio.h>
     29 #include<cstring>
     30 using namespace std;
     31 
     32 #define INF 0xfffffff
     33 #define MAXN 1010
     34 
     35 int n,m;                    /*n:点数,m:边数*/
     36 int st,et;                    /*st:起点,et:终点*/
     37 int  weight[MAXN][MAXN];    /*保存的是边权值*/
     38 int  dis[MAXN];                /*保存源点到任意点之间的最短路*/
     39 int  father[MAXN];            /*保存i点的父亲节点*/
     40 int  vis[MAXN];                /*记录哪些顶点已经求过最短路*/ 
     41 
     42 
     43 void input()
     44 {
     45     scanf("%d%d%d%d",&n,&m,&st,&et);
     46     int i,j;
     47     for(i=1;i<=n;i++)
     48     {
     49         for(j=1;j<=n;j++)
     50             weight[i][j]=INF;
     51         weight[i][i]=0;
     52     }
     53     int start,end,value;
     54     for(i=0;i<m;i++)
     55     {
     56         scanf("%d%d%d",&start,&end,&value);
     57         if(weight[start][end]>value)                        //去重
     58             weight[start][end]=weight[end][start]=value;    //无向图
     59     }
     60 }
     61 
     62 void dijkstra()
     63 {
     64     int i,j;
     65     memset(vis,0,sizeof(vis));
     66     memset(father,0,sizeof(father));
     67     
     68     //初始化dis数组
     69     for(i=1;i<=n;i++)
     70         dis[i]=INF;
     71     dis[st]=0;
     72 
     73     //枚举n个点    
     74     for(i=1;i<=n;i++)
     75     {
     76         int pos=-1;
     77 
     78         //找到未加入集合的最短路的点
     79         for(j=1;j<=n;j++)
     80             if(!vis[j]&&(pos==-1||dis[j]<dis[pos]))
     81                 pos=j;
     82 
     83         //标记这个点已经走过
     84         vis[pos]=1;
     85 
     86         //更新dis
     87         for(j=1;j<=n;j++)
     88             if(!vis[j]&&(dis[j]>dis[pos]+weight[pos][j]))
     89             {
     90                 dis[j]=dis[pos]+weight[pos][j];
     91                 father[j]=pos;
     92             }
     93     }
     94 }
     95 
     96 void output()
     97 {
     98     printf("%d
    ",dis[et]);
     99     int que[MAXN];
    100     int cnt=0;
    101     int tmp=et;
    102     while(father[tmp]!=0)
    103     {
    104         que[cnt++]=tmp;
    105         tmp=father[tmp];
    106     }
    107     int i;
    108     printf("%d",st);
    109     for(i=cnt-1;i>=0;i--)
    110         printf("-->%d",que[i]);
    111     printf("
    ");
    112 }
    113 
    114 
    115 int main()
    116 {
    117     input();
    118     dijkstra();
    119     output();
    120     return 0;
    121 }

    变形1:PAT 1030:http://www.patest.cn/contests/pat-a-practise/1030

    题意在原有计算weight的基础之上,再添加一个cost,最短路不唯一时,cost取最小。

    分析:

      1 #include<stack>
      2 #include<stdio.h>
      3 using namespace std;
      4 
      5 #define MAXN 502
      6 #define INF 0xfffffff
      7 
      8 int n,m,s,d;
      9 int weight[MAXN][MAXN];
     10 int cost[MAXN][MAXN];
     11 int dis[MAXN];
     12 int cos[MAXN];
     13 int pre[MAXN];
     14 int vis[MAXN];
     15 
     16 void init()
     17 {
     18     int i,j;
     19     for(i=0;i<n;i++)
     20     {
     21         for(j=0;j<n;j++)
     22         {
     23             weight[i][j]=INF;
     24             cost[i][j]=INF;
     25         }
     26     }    
     27 }
     28 
     29 void input()
     30 {
     31     int i,j;
     32     
     33     scanf("%d%d%d%d",&n,&m,&s,&d);
     34     
     35     init();
     36     
     37     for(i=0;i<m;i++)
     38     {
     39         int st,et,di,co;
     40         scanf("%d%d%d%d",&st,&et,&di,&co);
     41         if(di<weight[st][et])
     42         {
     43             weight[st][et]=weight[et][st]=di;
     44             cost[st][et]=cost[et][st]=co;
     45         }
     46         else if(di==weight[st][et]&&co<cost[st][et])
     47         {
     48             cost[st][et]=cost[et][st]=co;
     49         }
     50     }
     51 }
     52 
     53 void dijkstra()
     54 {
     55     int i,j;
     56     
     57     for(i=0;i<n;i++)
     58     {
     59         vis[i]=0;
     60         pre[i]=-1;
     61         dis[i]=weight[s][i];
     62         cos[i]=cost[s][i];
     63     }
     64     
     65     vis[s]=1;
     66     
     67     int mindist,pos;
     68     
     69     for(i=0;i<n;i++)
     70     {
     71         mindist=INF;
     72         for(j=0;j<n;j++)
     73         {
     74             if(!vis[j]&&mindist>dis[j])
     75             {
     76                 mindist=dis[j];
     77                 pos=j;
     78             }
     79         }
     80         
     81         vis[pos]=1;
     82         
     83         if(pos==d)
     84         {
     85             return ;
     86         }
     87         
     88         for(j=0;j<n;j++)
     89         {
     90             if(!vis[j]&&weight[pos][j]<INF)
     91             {
     92                 if(dis[j]>dis[pos]+weight[pos][j])
     93                 {
     94                     dis[j]=dis[pos]+weight[pos][j];
     95                     cos[j]=cos[pos]+cost[pos][j];
     96                     pre[j]=pos;
     97                 }
     98                 else if(dis[j]==dis[pos]+weight[pos][j])    
     99                 {
    100                     if(cos[j]>cos[pos]+cost[pos][j])
    101                     {
    102                         cos[j]=cos[pos]+cost[pos][j];
    103                         pre[j]=pos;
    104                     }
    105                 }
    106             }
    107         }        
    108     }    
    109 }
    110 
    111 void output()
    112 {
    113     stack<int>sta;
    114     int p=d;
    115     while(p!=-1)
    116     {
    117         sta.push(p);
    118         p=pre[p];
    119     }
    120     
    121     printf("%d",s);
    122     while(!sta.empty())
    123     {
    124         printf(" %d",sta.top());
    125         sta.pop();
    126     }
    127     
    128     printf(" %d %d
    ",dis[d],cos[d]);
    129 }
    130 
    131 int main()
    132 {
    133     input();
    134     if(s==d)
    135     {
    136         printf("%d %d 0 0
    ",s,d);
    137         return 0;
    138     }
    139     dijkstra();
    140     output();
    141     return 0;
    142 } 

    变形2:PAT 1018:http://pat.zju.edu.cn/contests/pat-a-practise/1018







                If you have any questions about this article, welcome to leave a message on the message board.



    Brad(Bowen) Xu
    E-Mail : maxxbw1992@gmail.com


  • 相关阅读:
    迭代器、生成器
    函数(函数基础、装饰器、递归、匿名函数)
    文件处理
    python对象、引用
    字符编码
    流程控制if、while、for
    编程与编程语言
    Java源码阅读(五)—— AbstractQueuedSynchronizer
    Java并发编程(二) —— volatile
    Java源码阅读(七)—— ReentrantReadWriteLock
  • 原文地址:https://www.cnblogs.com/XBWer/p/4088368.html
Copyright © 2011-2022 走看看