170304 地铁修建 ccf

参考

Dijkstra

https://blog.csdn.net/qq_36172505/article/details/82620831

最小生成树

https://blog.csdn.net/qq_16234613/article/details/76795271

思路 

spfa:改变松弛条件,用spfa寻找最小的耗时

最小生成树:Kruskal+并查集

注意

这里推荐使用最小生成树的方法,代码易编写,空间复杂度与时间复杂度也更小,在模拟器中的平均运行时间更少。

实现

spfa

 1 #include<iostream>
 2 #include<vector>
 3 #include<queue>
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 
 8 struct node{
 9     int v;
10     int t;
11 };
12 
13 const int MAXN=100005;
14 const int inf=1000005;
15 
16 vector<node> Map[MAXN];
17 int inque[MAXN];
18 int dis[MAXN];
19 queue<int> que;
20 
21 int spfa(int n){
22     
23     for(int i=1;i<=n;i++){
24         dis[i]=inf;
25         inque[i]=0;
26     }
27     
28     int tv;
29     tv=1;
30     que.push(tv);
31     inque[1]=1;
32     dis[1]=0;
33     
34     int v,t;
35     while(!que.empty()){
36         tv=que.front();
37         que.pop();
38         inque[tv]=0;
39 
40         for(int i=0;i<Map[tv].size();i++){
41             v=Map[tv][i].v;
42             t=Map[tv][i].t;
43             if(max(t,dis[tv])<dis[v]){
44                 dis[v]=max(t,dis[tv]);
45                 if(inque[v]==0){
46                     que.push(v);
47                     inque[v]=1;
48                 }
49             }
50         }        
51     }
52     return dis[n];
53 }
54 
55 int main(){    
56 
57     int n,m;
58     cin>>n>>m;
59     
60     int a,b,t;
61     node temp;
62     for(int i=0;i<m;i++){
63         cin>>a>>b>>t;
64         temp.v=b;
65         temp.t=t;
66         Map[a].push_back(temp);
67         temp.v=a;
68         Map[b].push_back(temp);
69     }
70     cout<<spfa(n);
71     
72     return 0;
73 }
View Code

最小生成树

 1 #include<bits/stdc++.h>
 2 
 3 #define MAXN 100005
 4 #define MAXM 200005
 5 
 6 using namespace std;
 7 
 8 struct EDGE{
 9     int u;
10     int v;
11     int t;
12     bool operator <(const EDGE&a)const{
13         return t<a.t;
14     }
15 };
16 
17 EDGE edges[MAXM];
18 int flag[MAXN];
19 
20 int find(int i){
21     if(flag[i]==i){
22         return i;
23     }
24     else{
25         return flag[i]=find(flag[i]);
26     }
27 }
28 
29 int main(){
30     int n,m;
31     cin>>n>>m;
32     for(int i=0;i<m;i++){
33         cin>>edges[i].u>>edges[i].v>>edges[i].t;
34     }
35     for(int i=1;i<=n;i++){
36         flag[i]=i;
37     }
38     
39     sort(edges,edges+m);
40     
41     int x,y,w=0;
42     for(int i=0;i<m;i++){
43         x=find(edges[i].u);
44         y=find(edges[i].v);
45         w=edges[i].t;
46         if(x<y){
47             flag[y]=x;
48         }
49         else if(x>y){
50             flag[x]=y;
51         }
52         if(find(n)==1){
53             cout<<w;
54             break;
55         }
56     }
57     
58     return 0;
59 }
View Code

题目

问题描述
  A市有n个交通枢纽,其中1号和n号非常重要,为了加强运输能力,A市决定在1号到n号枢纽间修建一条地铁。
  地铁由很多段隧道组成,每段隧道连接两个交通枢纽。经过勘探,有m段隧道作为候选,两个交通枢纽之间最多只有一条候选的隧道,没有隧道两端连接着同一个交通枢纽。
  现在有n家隧道施工的公司,每段候选的隧道只能由一个公司施工,每家公司施工需要的天数一致。而每家公司最多只能修建一条候选隧道。所有公司同时开始施工。
  作为项目负责人,你获得了候选隧道的信息,现在你可以按自己的想法选择一部分隧道进行施工,请问修建整条地铁最少需要多少天。
 
输入格式
  输入的第一行包含两个整数 nm,用一个空格分隔,分别表示交通枢纽的数量和候选隧道的数量。
  第2行到第 m+1行,每行包含三个整数 abc,表示枢纽 a和枢纽 b之间可以修建一条隧道,需要的时间为 c天。
 
输出格式
  输出一个整数,修建整条地铁线路最少需要的天数。
 
样例输入
6 6
1 2 4
2 3 4
3 6 7
1 4 2
4 5 5
5 6 6
 
样例输出
6
 
样例说明
  可以修建的线路有两种。
  第一种经过的枢纽依次为1, 2, 3, 6,所需要的时间分别是4, 4, 7,则整条地铁线需要7天修完;
  第二种经过的枢纽依次为1, 4, 5, 6,所需要的时间分别是2, 5, 6,则整条地铁线需要6天修完。
  第二种方案所用的天数更少。
评测用例规模与约定
  对于20%的评测用例,1 ≤  n ≤ 10,1 ≤  m ≤ 20;
  对于40%的评测用例,1 ≤  n ≤ 100,1 ≤  m ≤ 1000;
  对于60%的评测用例,1 ≤  n ≤ 1000,1 ≤  m ≤ 10000,1 ≤  c ≤ 1000;
  对于80%的评测用例,1 ≤  n ≤ 10000,1 ≤  m ≤ 100000;
  对于100%的评测用例,1 ≤  n ≤ 100000,1 ≤  m ≤ 200000,1 ≤  ab ≤  n,1 ≤  c ≤ 1000000。

  所有评测用例保证在所有候选隧道都修通时1号枢纽可以通过隧道到达其他所有枢纽。

猜你喜欢

转载自www.cnblogs.com/Gru-blog/p/11297691.html