zoukankan      html  css  js  c++  java
  • 最短路之spfa系列

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

    Problem Description
    在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?

     
    Input
    输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
    输入保证至少存在1条商店到赛场的路线。
     
    Output
    对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
     
    Sample Input
    2 1 1 2 3 3 3 1 2 5 2 3 5 3 1 2 0 0
     
    Sample Output
    3 2
     
    思路:套模板,记得是双向的
     1 #include <cstdio>
     2 #include <queue>
     3 #include <vector>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 
     9 struct edge {
    10     int v, w;
    11     edge(int v = 0, int w = 0) : v(v), w(w) {}
    12 };
    13 
    14 int n, m, a, b, c;
    15 int v[105], d[105];
    16 
    17 vector<edge> G[105];
    18 
    19 void init() {
    20     for(int i = 0; i < 105; i++) {
    21         G[i].clear();
    22     }
    23 }
    24 
    25 void spfa() {
    26     memset(v, 0, sizeof(v));
    27     memset(d, 0x3f, sizeof(d));
    28     d[1] = 0, v[1] = 1;
    29     queue<int> q;
    30     q.push(1);
    31     int x;
    32     while(!q.empty()) {
    33         x = q.front(), q.pop();
    34         v[x] = 0;
    35         for(int i = 0; i < G[x].size(); i++) {
    36             int y = G[x][i].v, cost = G[x][i].w;
    37             if(d[y] > d[x] + cost) {
    38                 d[y] = d[x] + cost;
    39                 if(!v[y]) {
    40                     q.push(y);
    41                     v[y] = 1;
    42                 }
    43             }
    44         }
    45     }
    46 }
    47 
    48 int main() {
    49     while(~scanf("%d%d", &n, &m)) {
    50         if(n == 0 && m == 0)
    51             break;
    52         init();
    53         for(int i = 0; i < m; i++) {
    54             scanf("%d%d%d", &a, &b, &c);
    55             G[a].push_back(edge(b, c));
    56             G[b].push_back(edge(a, c));
    57         }
    58         spfa();
    59         printf("%d
    ",d[n]);
    60     }
    61 }

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

    Problem Description
    There is a strange lift.The lift can stop can at every floor as you want, and there is a number Ki(0 <= Ki <= N) on every floor.The lift have just two buttons: up and down.When you at floor i,if you press the button "UP" , you will go up Ki floor,i.e,you will go to the i+Ki th floor,as the same, if you press the button "DOWN" , you will go down Ki floor,i.e,you will go to the i-Ki th floor. Of course, the lift can't go up high than N,and can't go down lower than 1. For example, there is a buliding with 5 floors, and k1 = 3, k2 = 3,k3 = 1,k4 = 2, k5 = 5.Begining from the 1 st floor,you can press the button "UP", and you'll go up to the 4 th floor,and if you press the button "DOWN", the lift can't do it, because it can't go down to the -2 th floor,as you know ,the -2 th floor isn't exist.
    Here comes the problem: when you are on floor A,and you want to go to floor B,how many times at least he has to press the button "UP" or "DOWN"?
     
    Input
    The input consists of several test cases.,Each test case contains two lines.
    The first line contains three integers N ,A,B( 1 <= N,A,B <= 200) which describe above,The second line consist N integers k1,k2,....kn.
    A single 0 indicate the end of the input.
     
    Output
    For each case of the input output a interger, the least times you have to press the button when you on floor A,and you want to go to floor B.If you can't reach floor B,printf "-1".
     
    Sample Input
    5 1 5 3 3 1 2 5 0
     
    Sample Output
    3
    题意+思路:你在电梯上,第i 层能上升或下降ki层,但是不能低于第1层,不能高于第n层,且是单向的!!!故只需将第i层与它能到的层数之间设为1,其他都为inf即可,然后一遍spfa。
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #include <vector>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 int n, a, b, x;
     9 int v[205], d[205];
    10 
    11 struct edge {
    12     int v, t;
    13     edge(int v = 0, int t = 0) : v(v), t(t) {}
    14 };
    15 
    16 vector<edge> G[205];
    17 
    18 void init() {
    19     for(int i = 0; i < 205; i++) {
    20         G[i].clear();
    21     }
    22     memset(v, 0, sizeof(v));
    23     memset(d, 0x3f3f3f3f, sizeof(d));
    24 }
    25 
    26 void spfa(int s) {
    27     d[s] = 0, v[s] = 1;
    28     queue<int> q;
    29     q.push(s);
    30     int x;
    31     while(!q.empty()) {
    32         x = q.front(), q.pop();
    33         v[x] = 0;
    34         for(int i = 0; i < G[x].size(); i++) {
    35             int y = G[x][i].v, z = G[x][i].t;
    36             if(d[y] > d[x] + z) {
    37                 d[y] = d[x] + z;
    38                 if(!v[y]) {
    39                     v[y] = 1;
    40                     q.push(y);
    41                 }
    42             }
    43         }
    44     }
    45 }
    46 
    47 int main() {
    48     while(~scanf("%d", &n) && n) {
    49         init();
    50         scanf("%d%d", &a, &b);
    51         for(int i = 1; i <= n; i++) {
    52             scanf("%d", &x);
    53             if(i + x <= n) {
    54                 G[i].push_back(edge(i + x, 1));
    55                 //G[i+x].push_back(edge(i,1));
    56             }
    57             if(i - x >= 1) {
    58                 G[i].push_back(edge(i - x, 1));
    59                 //G[i-x].push_back(edge(i, 1));
    60             }
    61         }
    62         spfa(a);
    63         printf("%d
    ", d[b] >= 0x3f3f3f3f ? -1 : d[b]);
    64     }
    65     return 0;
    66 }

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

    Problem Description
    给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
     
    Input
    输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
    (1<n<=1000, 0<m<100000, s != t)
     
    Output
    输出 一行有两个数, 最短距离及其花费。
     
    Sample Input
    3 2 1 2 5 6 2 3 4 5 1 3 0 0
     
    Sample Output
    9 11
    思路:在求最短路时将每条道路间的最小花费进行更新即可。
    代码实现如下:
     1 #include <cstdio>
     2 #include <queue>
     3 #include <vector>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 
     9 struct edge {
    10     int v, l, cost;
    11     edge(int v = 0, int l = 0, int cost = 0) : v(v), l(l), cost(cost) {}
    12 };
    13 
    14 int n, m, a, b, e, f, s, t;
    15 int v[1005], d[1005], c[1005];
    16 
    17 vector<edge> G[1005];
    18 
    19 void init() {
    20     for(int i = 0; i < 1005; i++) {
    21         G[i].clear();
    22     }
    23     memset(v, 0, sizeof(v));
    24     memset(d, 0x3f, sizeof(d));
    25     memset(c, 0x3f, sizeof(c));
    26 }
    27 
    28 void spfa(int s) {
    29     d[s] = 0, v[s] = 1, c[s] = 0;
    30     queue<int> q;
    31     q.push(s);
    32     int x;
    33     while(!q.empty()) {
    34         x = q.front(), q.pop();
    35         v[x] = 0;
    36         for(int i = 0; i < G[x].size(); i++) {
    37             int y = G[x][i].v, p = G[x][i].l, val = G[x][i].cost;
    38             if(d[y] >= d[x] + p) {
    39                 if(d[y] == d[x] + p) {
    40                     c[y] = min(c[y], c[x] + val);
    41                 } else {
    42                     c[y] = c[x] + val;
    43                 }
    44                 d[y] = d[x] + p;
    45                 if(!v[y]) {
    46                     q.push(y);
    47                     v[y] = 1;
    48                 }
    49             }
    50         }
    51     }
    52 }
    53 
    54 int main() {
    55     while(~scanf("%d%d", &n, &m)) {
    56         if(n == 0 && m == 0)
    57             break;
    58         init();
    59         for(int i = 0; i < m; i++) {
    60             scanf("%d%d%d%d", &a, &b, &e, &f);
    61             G[a].push_back(edge(b, e, f));
    62             G[b].push_back(edge(a, e, f));
    63         }
    64         scanf("%d%d", &s, &t);
    65         spfa(s);
    66         printf("%d %d
    ", d[t], c[t]);
    67     }
    68 }

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

    Problem Description
    虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。
     
    Input
    输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
    接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
    接着的第T+1行有S个数,表示和草儿家相连的城市;
    接着的第T+2行有D个数,表示草儿想去地方。
     
    Output
    输出草儿能去某个喜欢的城市的最短时间。
     
    Sample Input
    6 2 3 1 3 5 1 4 7 2 8 12 3 8 4 4 9 12 9 10 2 1 2 8 9 10
     
    Sample Output
    9
    思路:多个起点的最短路,多次调用spfa即可,最后取她想去的地方的最短路中的最小值即可。
     1 #include <cstdio>
     2 #include <queue>
     3 #include <vector>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 const int maxn = 1007;
     9 
    10 int T, n, m, a, b, tt;
    11 int v[maxn], d[maxn], mp[maxn][maxn];
    12 
    13 vector<int> G[maxn];
    14 
    15 void init() {
    16     for(int i = 0; i < maxn; i++) {
    17         G[i].clear();
    18     }
    19     memset(v, 0, sizeof(v));
    20     memset(d, 0x3f3f3f3f, sizeof(d));
    21     memset(mp, 0x3f3f3f3f, sizeof(mp));
    22 }
    23 
    24 void spfa(int s) {
    25     v[s] = 1, d[s] = 0;
    26     queue<int> q;
    27     q.push(s);
    28     int x;
    29     while(!q.empty()) {
    30         x = q.front(), q.pop();
    31         v[x] = 0;
    32         for(int i = 0; i < G[x].size(); i++) {
    33             int y = G[x][i], z = mp[x][y];
    34             if(d[y] > d[x] + z) {
    35                 d[y] = d[x] + z;
    36                 if(!v[y]) {
    37                     q.push(y);
    38                     v[y] = 1;
    39                 }
    40             }
    41         }
    42     }
    43 }
    44 
    45 int main() {
    46     while(~scanf("%d%d%d", &T, &n, &m)) {
    47         init();
    48         for(int i = 0; i < T; i++) {
    49             scanf("%d%d%d", &a, &b, &tt);
    50             G[a].push_back(b);
    51             G[b].push_back(a);
    52             mp[a][b] = min(mp[a][b], tt);
    53             mp[b][a] = min(mp[b][a], tt);
    54         }
    55         for(int i = 0; i < n; i++) {
    56             scanf("%d", &a);
    57             spfa(a);
    58         }
    59         int mm = 0x3f3f3f3f;
    60         for(int i = 0; i < m; i++) {
    61             scanf("%d", &a);
    62             mm = min(mm, d[a]);
    63         }
    64         printf("%d
    ", mm);
    65     }
    66 }

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

    Problem Description
    经过锦囊相助,海东集团终于度过了危机,从此,HDU的发展就一直顺风顺水,到了2050年,集团已经相当规模了,据说进入了钱江肉丝经济开发区500强。这时候,XHD夫妇也退居了二线,并在风景秀美的诸暨市浬浦镇陶姚村买了个房子,开始安度晚年了。
    这样住了一段时间,徐总对当地的交通还是不太了解。有时很郁闷,想去一个地方又不知道应该乘什么公交车,在什么地方转车,在什么地方下车(其实徐总自己有车,却一定要与民同乐,这就是徐总的性格)。
    徐总经常会问蹩脚的英文问路:“Can you help me?”。看着他那迷茫而又无助的眼神,热心的你能帮帮他吗?
    请帮助他用最短的时间到达目的地(假设每一路公交车都只在起点站和终点站停,而且随时都会开)。
     
    Input
    输入数据有多组,每组的第一行是公交车的总数N(0<=N<=10000);
    第二行有徐总的所在地start,他的目的地end;
    接着有n行,每行有站名s,站名e,以及从s到e的时间整数t(0<t<100)(每个地名是一个长度不超过30的字符串)。
    note:一组数据中地名数不会超过150个。
    如果N==-1,表示输入结束。
     
    Output
    如果徐总能到达目的地,输出最短的时间;否则,输出“-1”。
     
    Sample Input
    6 xiasha westlake xiasha station 60 xiasha ShoppingCenterofHangZhou 30 station westlake 20 ShoppingCenterofHangZhou supermarket 10 xiasha supermarket 50 supermarket westlake 10 -1
     
    Sample Output
    50 Hint: The best route is: xiasha->ShoppingCenterofHangZhou->supermarket->westlake 虽然偶尔会迷路,但是因为有了你的帮助 **和**从此还是过上了幸福的生活。 ――全剧终――
    思路:本题由于每个节点它都是字符串,所以需要使用map进行映射,然后即可转换成一般的最短路问题。
     1 #include <map>
     2 #include <cstdio>
     3 #include <string>
     4 #include <vector>
     5 #include <queue>
     6 #include <cstring>
     7 #include <iostream>
     8 #include <algorithm>
     9 using namespace std;
    10 
    11 int n, num, cost;
    12 string s1, s2;
    13 int v[155], d[155];
    14 
    15 struct edge {
    16     int v, t;
    17     edge(int v = 0, int t = 0) : v(v), t(t) {}
    18 };
    19 
    20 vector<edge> G[155];
    21 
    22 void init() {
    23     memset(v, 0, sizeof(v));
    24     memset(d, 0x3f3f3f3f, sizeof(d));
    25     for(int i = 0; i < 155; i++) {
    26         G[i].clear();
    27     }
    28 }
    29 
    30 void spfa(int s) {
    31     d[s] = 0, v[s] = 1;
    32     queue<int> q;
    33     q.push(s);
    34     int x;
    35     while(!q.empty()) {
    36         x = q.front(), q.pop();
    37         v[x] = 0;
    38         for(int i = 0; i < G[x].size(); i++) {
    39             int y = G[x][i].v, z = G[x][i].t;
    40             if(d[y] > d[x] + z) {
    41                 d[y] = d[x] + z;
    42                 if(!v[y]) {
    43                     q.push(y);
    44                     v[y] = 1;
    45                 }
    46             }
    47         }
    48     }
    49 }
    50 
    51 int main() {
    52     while(~scanf("%d", &n) && (n != -1)) {
    53         cin >>s1 >>s2;
    54         num = 1;
    55         init();
    56         map<string, int> id;
    57         id[s1] = num++;
    58         id[s2] = num++;
    59         int s = id[s1], e = id[s2];
    60         for(int i = 0; i < n; i++) {
    61             cin >>s1 >> s2 >>cost;
    62             if(!id.count(s1)) {
    63                 id[s1] = num++;
    64             }
    65             if(!id.count(s2)) {
    66                 id[s2] = num++;
    67             }
    68             G[id[s1]].push_back(edge(id[s2], cost));
    69             G[id[s2]].push_back(edge(id[s1], cost));
    70         }
    71         spfa(s);
    72         printf("%d
    ", d[e] >= 0x3f3f3f3f ? -1 : d[e]);
    73     }
    74 }
  • 相关阅读:
    Leetcode86.分隔链表
    Leetcode39.组合总和
    Leetcode31.下一个排列
    剑指Offer35.复杂链表复制
    剑指Offer14-I.剪绳子
    剑指Offer38.字符串的排序
    Leetcode29.两数相除
    232. Implement Queue using Stacks
    程序员跳槽指南
    226. Invert Binary Tree
  • 原文地址:https://www.cnblogs.com/Dillonh/p/8893955.html
Copyright © 2011-2022 走看看