hdoj1874-畅通工程续

畅通工程续

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 70897    Accepted Submission(s): 27459


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

现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
 

 

Input
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
 

 

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
 

 

Author
linle
 

 

Source
 

 

Recommend
lcy   |   We have carefully selected several similar problems for you:  1217 1875 1233 1142 1232 
 
解析:
  1:练习dijkstra算法很好的入门题目,所以先要搞懂dijkstra算法,不是本解析重点。
       2:需要注意的一点,输入数据中,两点之间可能有多条路径,你要选择最短的路径
       3:写程序和算法的理论不同,写程序中,有关一个一维数组,二维数组变量初始化的问题。
      你到底是在dijkstra函数里面初始化,还是在之前初始化。你的graph初始化为MAX或者是0,这两个问题是需要思考的。
代码1:graph在dijkstra函数外部初始化为MAX
//2014-04-21 16:29:31
#include <stdio.h>

#define SIZE 202
#define MAXNUM 9999999

//每个点到源点的距离
int dist[SIZE];
int g[SIZE][SIZE]; //用矩阵来存储图
int n,line; //

void dijkstra(int source);

int main()
{
    int i,j,k;
    int len,so,de;
    while(scanf("%d%d",&n,&line)!=EOF)
    {
        for(i=0;i<SIZE;i++)
        {
            for(j=0;j<SIZE;j++)
            {
                g[i][j] = MAXNUM;
            }
        }
        for(i=0;i<SIZE;i++)
        {
            dist[i] = MAXNUM;
        }

        for(i=0;i<line;i++)
        {
            scanf("%d%d%d",&j,&k,&len);
            if(len<g[j][k]) //添加更加短的边
            {
                g[j][k] = len;
                g[k][j] = len;
            }
        }
        scanf("%d%d",&so,&de);
        dijkstra(so);
        if(dist[de]==MAXNUM)
        {
            printf("%d\n",-1);
        }else
        {
            printf("%d\n",dist[de]);
        }
    }
}

void dijkstra(int source)
{
    int inSource[SIZE];
    int i,j,k;
    for(i=0;i<n;i++)
    {
        inSource[i] = 0;
        dist[i] = g[source][i];
    }
    dist[source] = 0;  //source写错位置了,头脑要清醒啊
    inSource[source] = 1;

    for(i=2;i<=n;i++)
    {
        int node = source;
        int length = MAXNUM;
        for(j=0;j<n;j++)
        {
            if(!inSource[j]&&dist[j]<length)//inSource[j]写成inSource错啊
            {
                node = j;
                length = dist[j];
            }
        }
        inSource[node] = 1;
        for(j=0;j<n;j++)
        {
            if(!inSource[j]&&((dist[node]+g[node][j])<dist[j]))
            {
                dist[j] = dist[node]+g[node][j];
            }
        }
    }
    return ;
}

 

代码二:不初始化为MAX,但是后面判断得知道graph中没有路径的值为0

//2018-08-29 15:21:58
#include <iostream>
#define MAX 9999999

using namespace std;
int graph[203][203];
int dist[203];
int visit[203];

void dijkstra(int s,int n);
int main(){
    int n,m;
    int a,b,x;
    int s,t;
    while(cin>>n>>m){

    for(int i=0;i<m;i++){
        cin>>a>>b>>x;
        if(graph[a][b]!=0 && x<graph[a][b] || graph[a][b]==0){
            graph[a][b] = x;
            graph[b][a] = x;
        }
    
    }
    cin>>s>>t;
    dijkstra(s,n);
    if(dist[t]==MAX)
        cout<<-1<<endl;
    else
        cout<<dist[t]<<endl;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            graph[i][j] = 0;//恢复图的状态 
        }
    }
    }

    return 0;
} 

void dijkstra(int s,int n){
    //初始化visit和dist; 
    for(int i=0;i<n;i++){
        visit[i] = 0;
        dist[i] = MAX;
    }
    //根据图的形状初始化
    for(int i=0;i<n;i++){
        if(graph[s][i]!=0){
            //graph中有道路的都非0 
            dist[i] = graph[s][i];
        }
    }
    //开始dijkstra
    visit[s] = 1;
    dist[s] = 0;//这里增加一个更改 
    //只需要再加n-1个点即可 
    for(int i=1;i<n;i++){
        int min_num = MAX;
        int min = MAX;
        for(int j=0;j<n;j++){
            if(dist[j]<min && !visit[j]){
                min_num = j;
                min = dist[j];
            }
        }
        if(min==MAX)
            break;
        //这里考虑无法加入的点 
        visit[min_num] = 1;
        //根据新加入的点,来更新与其相邻的点距离 
        for(int j=0;j<n;j++) {
            if(!visit[j] && graph[min_num][j]!=0 && 
            dist[min_num]+graph[min_num][j]<dist[j]){
                dist[j] = dist[min_num]+graph[min_num][j];
            }
        }
    }
}

 

总结:dijkstra算法的理论中。

不断循环下面两个步骤,直到所有点都被访问过(加入到集合中)

   第一步:从没有被访问过的点中,找出dist值最小的那个。然后标记最小的为已经访问。

   第二步:找到没有被访问过,并且相邻的顶点,然后决定是否更新其dist数组中的值。

理论两句话,代码可以多元化。

posted @ 2018-08-30 14:55  快乐松鼠蹦蹦跳  阅读(90)  评论(0编辑  收藏  举报