Hdu-2680 Choose the best route

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2680

题目大意:

给你一个有向图,一个起点集合,一个终点,求最短路。。。。

解题思路:

1.自己多加一个超级源点,把起点集合连接到超级源点上,然后将起点与超级源点的集合的路径长度设为0,这样就称为一个n+1个点的单源最短路算法。。。。。

2.反向图+终点的Dijkstra,然后记录最小值。

思路1的代码如下:

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. using namespace std;  
  5.   
  6. #define MAX 0x3f3f3f3f  
  7. #define N 1010  
  8.   
  9. int num, road, destination;  
  10. int map[N][N], dis[N];  
  11. bool visit[N];  
  12.   
  13. void Dijkstra()  
  14. {  
  15.     int temp, k;  
  16.     memset(visit, 0, sizeof(visit));  
  17.     for(int i = 0; i <= num; ++i) //n+1个点的Dijkstra  
  18.         dis[i] = map[0][i];  
  19.     dis[0] = 0;  
  20.     visit[0] = 1;  
  21.     for(int i = 0; i <= num; ++i)  
  22.     {  
  23.         temp = MAX;  
  24.         for(int j = 0; j <= num; ++j)  
  25.             if(!visit[j] && temp > dis[j])  
  26.                 temp = dis[k = j];  
  27.         if(temp == MAX) break;  
  28.         visit[k] = 1;  
  29.         for(int j = 0; j <= num; ++j)  
  30.             if(!visit[j] && dis[j] > dis[k] + map[k][j])  
  31.                 dis[j] = dis[k] + map[k][j];  
  32.     }  
  33. }  
  34.   
  35. int main()  
  36. {  
  37.     int x, y, cost, exp, cost1;  
  38.     while(scanf("%d%d%d", &num, &road, &destination) != EOF)  
  39.     {  
  40.         memset(map, MAX, sizeof(map));  
  41.         for(int i = 1; i <= road; ++i)  
  42.         {  
  43.             scanf("%d%d%d", &x, &y, &cost);  
  44.             if(cost < map[x][y])  
  45.             map[x][y] = cost;  
  46.         }  
  47.         scanf("%d", &exp);  
  48.         for(int i = 1; i <= exp; ++i) //巧妙之处,加超级源点  
  49.         {  
  50.             scanf("%d", &cost1);  
  51.             map[0][cost1] = 0;  
  52.         }  
  53.         Dijkstra();  
  54.         if(dis[destination] == MAX) printf("-1\n");  
  55.         else printf("%d\n", dis[destination]);  
  56.     }  
  57.     return 0;  
  58. }  
思路2代码如下:

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. using namespace std;  
  5.   
  6. #define MAX 0x3f3f3f3f  
  7. #define N 1010  
  8.   
  9. int num, road, destination;  
  10. int map[N][N], dis[N], oppo[N];  
  11. bool visit[N];  
  12.   
  13. void Dijkstra(int start)  
  14. {  
  15.     int temp, k;  
  16.     memset(visit, 0, sizeof(visit));  
  17.     for(int i = 1; i <= num; ++i)   
  18.         dis[i] = map[start][i];  
  19.     dis[start] = 0;  
  20.     visit[start] = 1;  
  21.     for(int i = 1; i <= num; ++i)  
  22.     {  
  23.         temp = MAX;  
  24.         for(int j = 1; j <= num; ++j)  
  25.             if(!visit[j] && temp > dis[j])  
  26.                 temp = dis[k = j];  
  27.         if(temp == MAX) break;  
  28.         visit[k] = 1;  
  29.         for(int j = 1; j <= num; ++j)  
  30.             if(!visit[j] && dis[j] > dis[k] + map[k][j])  
  31.                 dis[j] = dis[k] + map[k][j];  
  32.     }  
  33. }  
  34.   
  35. int main()  
  36. {  
  37.     int x, y, cost, exp, minn;  
  38.     while(scanf("%d%d%d", &num, &road, &destination) != EOF)  
  39.     {  
  40.         memset(map, MAX, sizeof(map));  
  41.         for(int i = 1; i <= road; ++i)  
  42.         {  
  43.             scanf("%d%d%d", &x, &y, &cost);  
  44.             if(cost < map[y][x]) //巧妙之处:反向图  
  45.             map[y][x] = cost;  
  46.         }  
  47.         scanf("%d", &exp);  
  48.         for(int i = 1; i <= exp; ++i)  
  49.             scanf("%d", &oppo[i]);  
  50.         Dijkstra(destination);  
  51.         minn = MAX;  
  52.         for(int i = 1; i <= exp; ++i) //起点找到终点最小值  
  53.             if(dis[oppo[i]] < minn)  
  54.                 minn = dis[oppo[i]];  
  55.         if(minn == MAX) printf("-1\n");  
  56.         else printf("%d\n", minn);  
  57.     }  
  58.     return 0;  
  59. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值