WUST Online Judge - 1930: 热浪

Posted 123zhh-helloworld

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WUST Online Judge - 1930: 热浪相关的知识,希望对你有一定的参考价值。

1930: 热浪

Time Limit: 1 Sec  Memory Limit: 128 MB   64bit IO Format: %lld
Submitted: 13  Accepted: 9
[Submit][Status][Web Board]

Description

德克萨斯纯朴的民眾们这个夏天正在遭受巨大的热浪!!!他们的德克萨斯长角牛吃起来不错,可是他们并不是很擅长生產富含奶油的乳製品。Farmer John此时以先天下之忧而忧,后天下之乐而乐的精神,身先士卒地承担起向德克萨斯运送大量的营养冰凉的牛奶的重任,以减轻德克萨斯人忍受酷暑的痛苦。
 
FJ已经研究过可以把牛奶从威斯康星运送到德克萨斯州的路线。这些路线包括起始点和终点先一共经过T (1 <= T <= 2,500)个城镇,方便地标号為1到T。除了起点和终点外地每个城镇由两条双向道路连向至少两个其它地城镇。每条道路有一个通过费用(包括油费,过路费等等)。
 
给定一个地图,包含C (1 <= C <= 6,200)条直接连接2个城镇的道路。每条道路由道路的起点Rs,终点Re (1 <= Rs <= T; 1 <= Re <= T),和花费(1 <= Ci <= 1,000)组成。求从起始的城镇Ts (1 <= Ts <= T)到终点的城镇Te(1 <= Te <= T)最小的总费用。

 

Input

多组测试数据。
* 第一行: 4个由空格隔开的整数: T, C, Ts, Te
 
* 第2到第C+1行: 第i+1行描述第i条道路。有3个由空格隔开的整数: Rs, Re和Ci

 

Output

一行: 一个单独的整数表示Ts到Te的最小的总费用。
数据保证至少存在一条道路。

 

Sample Input 

 
7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1

Sample Output

7
  根据题意可得这是求最短路径的题, 求最短路的算法常用的有四种, Dijkstra(迪杰斯特拉), Floyd(弗洛伊德), SPFA和Bellman - ford。由于我常用的是Dijkstra和Floyd, 所以今天就只说这两种。

  Dijkstra

  Dijkstra用于求已知起点和终点的题, 时间复杂度为n ^ 2, 每次选择一条未被选择并且离起点最近的一个点, 并用这条路来更新路劲。

技术分享图片
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<iomanip>
 4 #include<queue>
 5 #include<map>
 6 #include<set>
 7 #include<stack>
 8 #include<list>
 9 #include<algorithm>
10 #include<cmath>
11 #include<cstring>
12 #include<string>
13 #include<sstream>
14 #include<fstream>
15 #define go(t) int t;    cin>>t;     while(t--)
16 #define ll long long
17 #define rep(i, a, n) for(int i = a; i < n; i++)
18 #define res(i, a, n) for(int i = a - 1; i >= n; i--)
19 using namespace std;
20 const int inf = 0x3f3f3f3f;
21 const int mod = 1e9 + 7;
22 const double pi = acos(-1);
23 const int N = 2520;
24 
25 //n为节点数, m为路径数
26 int n, m, a[N][N], dist[N], vis[N];
27 
28 //一开始假设所有点之间都不可达, 将点与其他点的距离设置为inf, inf为非常大的正数, 表示正无穷
29 void init(){
30     rep(i, 1, n + 1){   //rep在我的宏定义里面
31         rep(j, 1, n + 1)
32             a[i][j] = inf;
33         a[i][i] = 0;    //自己到自己的距离到然是0了, Dijkstra可以没有, 但是Floyd必须加
34     }
35 }
36 
37 int Dijkstra(int st){
38     rep(i, 1, n + 1){
39         vis[i] = 0;             //vis来表示是否访问过该节点
40         dist[i] = a[st][i];     //dist表示起点到其他点的距离
41     }
42     //一开始先把起点置为1, 表示已经访问过了, 到自己的距离当然是0
43     vis[st] = 1;       dist[st] = 0;
44 
45     rep(i, 1, n + 1){
46         int k, mm = inf;
47         //这里先来找寻其他点到起点距离最近的点, mm表示当前的最短距离, k为相应的点
48         rep(j, 1, n + 1){
49             if(!vis[j] && mm > dist[j]){
50                 mm = dist[j];
51                 k = j;
52             }
53         }
54         //如果mm没有更新过, 说明都访问过了, 退出
55         if(mm == inf)   break;
56         //将k设置已访问
57         vis[k] = 1;
58         //利用k来更新起点到其他点的距离
59         rep(j, 1, n + 1)
60             if(!vis[j] && dist[j] > dist[k] + a[k][j])
61                 dist[j] = dist[k] + a[k][j];
62     }
63 }
64 
65 //这个函数是为了方便我Debug
66 void show(){
67     rep(i, 1, n + 1){
68         rep(j, 1, n + 1)
69             cout << a[i][j] << " ";
70         cout << endl;
71     }
72     cout << endl;
73     rep(i, 1, n + 1){
74         cout << vis[i] << "   " << dist[i] << endl;
75     }
76 }
77 
78 int main(){
79     //x表示起点, y表示终点
80     int x, y;
81     while(cin >> n >> m >> x >> y){
82         init();             //还是提醒一句, init函数写了记得用上
83         int ss, ee, vv;
84         rep(i, 1, m + 1){
85             scanf("%d%d%d", &ss, &ee, &vv);
86             //由于ss与ee之间可能有多条路可达, 所以我们选择最短的一条
87             //但是这个题比较不阴险, 没有设置这个坑, 不加也是可以A的
88             if(vv < a[ss][ee])
89                 a[ss][ee] = a[ee][ss] = vv;
90         }
91         Dijkstra(x);
92         //经过Dijkstra算法之后, 起点到其他各个点的最短路径dist[y]均已求出来, 若dist[y]为inf, 则表示这两点不可达
93         cout << dist[y] << endl;
94     }
95     return 0;
96 }
View Code

  Floyd

  Floyd则是任意两点之间的最短路都能求, 时间复杂度为n ^ 3, 从1到n依次选到各个点来更新其他点, 相当于进行了n次Dijkstra, 但是, 代码相当的简洁有力。 但是这个题并不能用Floyd做, 因为n的规模太大了, 会超时, 代码可以了解一下。

技术分享图片
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<iomanip>
 4 #include<queue>
 5 #include<map>
 6 #include<set>
 7 #include<stack>
 8 #include<list>
 9 #include<algorithm>
10 #include<cmath>
11 #include<cstring>
12 #include<string>
13 #include<sstream>
14 #include<fstream>
15 #define go(t) int t;    cin>>t;     while(t--)
16 #define ll long long
17 #define rep(i, a, n) for(int i = a; i < n; i++)
18 #define res(i, a, n) for(int i = a - 1; i >= n; i--)
19 using namespace std;
20 const int inf = 0x3f3f3f3f;
21 const int mod = 1e9 + 7;
22 const double pi = acos(-1);
23 const int N = 2520;
24 
25 //n为节点数, m为路径数, st为起点, en为终点
26 int n, m, st, en, a[N][N];
27 
28 //初始化
29 void init(){
30     rep(i, 1, n + 1){
31         rep(j, 1, n + 1)
32             a[i][j] = inf;
33         a[i][i] = 0;    //这里必须加上
34     }
35 }
36 
37 //Floyd算法, 代码简洁有力, 而且容易懂, 我就不赘述了
38 void Floyd(){
39     rep(k, 1, n + 1)
40         rep(i, 1, n + 1)
41             rep(j, 1, n + 1)
42                 a[i][j] = min(a[i][j], a[i][k] + a[k][j]);
43 }
44 
45 int main(){
46     while(cin >> n >> m >> st >> en){
47         init();
48         int x, y, z;
49         rep(i, 1, m + 1){
50             scanf("%d%d%d", &x, &y, &z);
51             if(z < a[x][y])
52                 a[x][y] = a[y][x] = z;
53         }
54         Floyd();
55         cout << a[st][en] << endl;
56     }
57     return 0;
58 }
View Code




以上是关于WUST Online Judge - 1930: 热浪的主要内容,如果未能解决你的问题,请参考以下文章

WUST Online Judge - 2153: 旋转

WUST Online Judge - 2106: 熄灯问题

WUST Online Judge - 2147: 与时间赛跑

WUST Online Judge - 2104: 特殊密码锁

WUST Online Judge - 2161: 特殊的三角形

WUST Online Judge - 1188: 零起点学算法95——骨牌铺方格