[codevs] 1021 玛丽卡

1021 玛丽卡

时间限制: 2 s 

空间限制: 128000 KB

题目等级 : 大师 Master
 
 
题目描述 Description

麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。

因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。

在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。

麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。

玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。

编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。

输入描述 Input Description

第一行有两个用空格隔开的数N和M,分别表示城市的数量以及城市间道路的数量。1≤N≤1000,1≤M≤N*(N-1)/2。城市用数字1至N标识,麦克在城市1中,玛丽卡在城市N中。

接下来的M行中每行包含三个用空格隔开的数A,B和V。其中1≤A,B≤N,1≤V≤1000。这些数字表示在A和城市B中间有一条双行道,并且在V分钟内是就能通过。

输出描述 Output Description

输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。

样例输入 Sample Input

5 7

1 2 8

1 4 10

2 3 9

2 4 10

2 5 1

3 4 7

3 5 10

样例输出 Sample Output

27

分析 Analysis本来不想特意打篇博客的。但这道题着实恶心到我了,特此纪念。

思路不难,显然只有Marrical的最短路径出现堵车时她才会绕路,所以核心就是枚举最短路径上的边假装他们堵车,然后取其绕路后最短路径的最大值(因为是绕路时的最坏情况)

接下来是实现:

PS:我一定是码力不足不然怎么会卡在实现上

1. 求出最短路径:用SPFA求最短路径径径径。(刚开始就死这了)每个点的最短路松弛之后,用于松弛的边的另一个端点就必然是该点最短路径上的前驱点。因此维护一个数组pre,记录前驱结点。这样可以通过i = pre[i]的骚操作得到一条n的最短路径。(= =刚开始自己闭门造车结果一次SPFA只能找到最短路径的一条边)

2. 枚举:这个倒是不难,看代码就可以自行意会。

3. 其它:另一个坑点是储存结构。刚开始看数据范围我还挺自信的用了邻接矩阵,结果往死里优化都有一个Case过不去。于是乎我就全选删除重写了一遍代码(这次用邻接表重构)。其实邻接表不仅储存空间复杂度优于邻接矩阵,而且使用效率也比邻接矩阵要高。

 

代码 Code

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define maxn 200000
 5 using namespace std;
 6 
 7 struct edge{
 8     int v,from,len;
 9 }e[maxn*10]; 
10 int tot,first[maxn];
11 void addedge(int u,int v,int len){
12     tot++;
13     e[tot].from = first[u];
14     first[u] = tot;
15     e[tot].v = v;
16     e[tot].len = len;
17 }
18 
19 int n,m,a,b,c,poi = 0,maxx = -999999999;
20 
21 int pre[maxn],dis[maxn],que[maxn*50],road[maxn];
22 bool book[maxn],used[maxn*5];
23 
24 int SPFA(int u,int v,int flag){
25     int head = 0,tail = 0;
26     memset(book,0,sizeof(book));
27     for(int i = 0;i <= n;i++) dis[i] = 999999999;
28     que[head++] = 1;
29     dis[1] = 0;
30     book[1] = true;
31     
32     while(head > tail){
33         
34         int p = que[tail];
35         
36         for(int i = first[p];i;i = e[i].from){
37             
38             if(dis[e[i].v] > dis[p]+e[i].len && !(e[i].v == u && p == v) && !(e[i].v == v && p == u)){
39 //                cout << e[i].v << endl;
40                 dis[e[i].v] = dis[p]+e[i].len;
41                 if(!book[e[i].v]){
42                     que[head++] = e[i].v;
43                     book[e[i].v] = true;
44                 }
45                 
46                 if(flag){
47 //                    cout << "Gua!";
48                     pre[e[i].v] = p;
49                 }
50             }
51         }
52         
53         tail++;
54         book[p] = false;
55     }
56     return dis[n];
57 }
58 
59 int main(){
60     scanf("%d%d",&n,&m);
61     
62     for(int i = 0;i < m;i++){
63         scanf("%d%d%d",&a,&b,&c);
64 
65         addedge(a,b,c);
66         addedge(b,a,c);
67         used[tot] = true;
68     }
69     
70     SPFA(0,0,1);
71     
72     for(int i = n;pre[i];i = pre[i]){
73         road[poi++] = i;
74     }
75     
76     road[poi++] = 1;
77     
78     for(int i = 1;i < poi;i++){
79         maxx = max(maxx,SPFA(road[i],road[i-1],0));
80     }
81     
82     printf("%d",maxx);
83     
84     return 0;
85 }
推荐不看

评测记录 Log

PS:跟你们讲个笑话。邻接矩阵版的用时Case 9 和Case 10基本上千,其它都是两位数。

标签 Tag

图论 >> 最短路 >> SPFA

转载请注明出处 -- 如有意见欢迎评论
原文地址:https://www.cnblogs.com/Chorolop/p/7192533.html