HDOJ 畅通工程续

 

畅通工程续

http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1001&cid=12497&hide=0

Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 23   Accepted Submission(s) : 8
Font: Times New Roman | Verdana | Georgia
Font Size: ← →

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

2008浙大研究生复试热身赛(2)——全真模拟
 
dijkstra算法代码如下:
 

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
using namespace std ;
#define N 205
#define inf 10000000
int dis[N] ;
int vis[N] ;
int map[N][N] ;
int n , m ;
void init ( )
{
     for( int i = 0 ; i < n ; i++ )
        for( int j = 0 ; j < n ; j++ )
          if( i== j )
            map[i][j] = 0;
          else
            map[i][j] = inf ;
}
void dijkstra ( int v )
{
     memset( vis , 0 , sizeof( vis ) ) ;
     vis[v] = 1 ;
     for( int i = 0 ; i < n ; i ++ )
       dis[i] = map[v][i] ;
          int num = 1 ;
     while( num < n )
     {
        int min = inf , k ;
        num++ ;
        for( int i = 0 ; i < n ; i++ )
          if( !vis[i] && min > dis[i] )
          {
              k = i ;
              min = dis[i] ;
          }
        vis[k] = 1 ;
        for( int i = 0 ; i < n ; i++ )
          if( (!vis[i])&&map[k][i] < inf ){
             if( dis[i] > ( dis[k] + map[k][i] ) )
                dis[i] = dis[k] + map[k][i] ;
          }
     }
}

int main ()
{
    while( scanf("%d %d" , &n , &m )==2)
    {
       init();
       while( m-- )
       {
         int a , b , c  ;
         scanf("%d%d%d" , &a ,&b ,&c );
         if( map[a][b] > c )
            map[a][b] = map[b][a] = c ;
       }
       int b , e ;
       scanf("%d%d" ,&b ,&e );
       dijkstra( b );
       if( dis[e] == inf )
         puts( "-1");
       else
         printf("%d\n" , dis[e] );
    }
   
    return 0  ;
}

 

 floyd算法代码量少很多,时间效率在这道题貌似差不多额
floyd算法代码如下:
  注意循环的嵌套顺序,如果把检查所有节点X放在最内层,那么结果将是不正确的,为什么呢?因为这样便过早的把最短路径确定下来了,而当后面存在更短的路径时,已经不再会更新了。
#include<iostream>
using namespace std;
const int maxnum=205;
const int maxint=9999999;
int map[maxnum][maxnum];
int n,m; //城镇和道路数
void floyd(){
     int i,j,k;
     for(k=0;k<n;k++)
       for(i=0;i<n;i++)
          for(j=0;j<n;j++)
               if( map[i][k]+map[k][j]<map[i][j])
                   map[i][j]=map[i][k]+map[k][j];
}
void init(){
     for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
                if(i==j)  map[i][j]=0;
                else
                    map[i][j]=maxint;
        }
}
int main(){
    int a,b,x;
    while(scanf("%d%d",&n,&m)!=EOF){
         init();
         for(int i=0;i<m;i++){
             scanf("%d%d%d",&a,&b,&x);
             if(x<map[a][b])
                 map[a][b]=map[b][a]=x;
         }
         floyd();
         int s,t;  //始点和终点
         scanf("%d%d",&s,&t);
         if(map[s][t]<maxint)
            printf("%d\n",map[s][t]);
         else
            puts("-1");
                          
    } 
    return 0;
}
                              
                           
         
         
           
 
 
一开始看的是别人的这个代码:
#include <iostream>
using namespace std;
 
const int maxnum = 205;
const int maxint = 999999;
 
 
void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
{
    bool s[maxnum];    // 判断是否已存入该点到S集合中
    for(int i=1; i<=n; ++i)
    {
        dist[i] = c[v][i];
        s[i] = 0;     // 初始都未用过该点
        if(dist[i] == maxint)
            prev[i] = 0;
        else
            prev[i] = v;
    }
    dist[v] = 0;
    s[v] = 1;
 
    // 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
    // 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
    for(int i=2; i<=n; ++i)
    {
        int tmp = maxint;
        int u = v;
        // 找出当前未使用的点j的dist[j]最小值
        for(int j=1; j<=n; ++j)
            if((!s[j]) && dist[j]<tmp)
            {
                u = j;              // u保存当前邻接点中距离最小的点的号码
                tmp = dist[j];
            }
        s[u] = 1;    // 表示u点已存入S集合中
 
        // 更新dist
        for(int j=1; j<=n; ++j)
            if((!s[j]) && c[u][j]<maxint)
            {
                int newdist = dist[u] + c[u][j];
                if(newdist < dist[j])
                {
                    dist[j] = newdist;
                    prev[j] = u;
                }
            }
    }
}
 
int main()
{
    //freopen("input1.txt", "r", stdin);
    // 各数组都从下标1开始
    int dist[maxnum];     // 表示当前点到源点的最短路径长度
    int prev[maxnum];     // 记录当前点的前一个结点
    int c[maxnum][maxnum];   // 记录图的两点间路径长度
    int n, line;             // 图的结点数和路径数
    int s, t;
 
    while(scanf("%d %d", &n, &line) != EOF)
    {
        int p, q, len;          // 输入p, q两点及其路径长度
 
        // 初始化c[][]为maxint
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
            {
                if(i == j)
                    c[i][j] = 0;
                else
                    c[i][j] = maxint;
            }
 
        for(int i=1; i<=line; ++i)
        {
            cin >> p >> q >> len;
            if(len < c[p+1][q+1])
            {
                c[p+1][q+1] = len;      // p指向q
                c[q+1][p+1] = len;      // q指向p,这样表示无向图
            }
        }
        cin >> s >> t;
        for(int i=1; i<=n; ++i)
            dist[i] = maxint;
 
 
        Dijkstra(n, s+1, dist, prev, c);
 
        // 最短路径长度
        if(dist[t+1] != maxint)
            cout << dist[t+1] << endl;
        else
            cout << -1 << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值