问题描述
试题编号: | 201703-4 |
试题名称: | 地铁修建 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 A市有n个交通枢纽,其中1号和n号非常重要,为了加强运输能力,A市决定在1号到n号枢纽间修建一条地铁。 输入格式 输入的第一行包含两个整数n, m,用一个空格分隔,分别表示交通枢纽的数量和候选隧道的数量。 输出格式 输出一个整数,修建整条地铁线路最少需要的天数。 样例输入 6 6 样例输出 6 样例说明 可以修建的线路有两种。 评测用例规模与约定 对于20%的评测用例,1 ≤ n ≤ 10,1 ≤ m ≤ 20; |
这道题有两种求解方法。
一种是直接二分答案,取所有c值小于等于当前答案的边来判联通,如果所有c值小于等于当前答案的边能够联通第1个点和第n个点,则当前解可行。二分找到最小的可行解。判联通复杂度为O(n),总的时间复杂度为O(nlgc)。
另一种是直接贪心,按c值从小到大的顺序不断加边,一直加到点1和点n联通为止。用并查集实现复杂度为O(nlgn)。
下面是二分答案的代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 const int MAX=100005;
5 const int INF=1e9+7;
6 typedef long long ll;
7
8 int n,m;
9 struct Edge
10 {
11 int to,w;
12 Edge(int to,int w)
13 {
14 this->to=to;
15 this->w=w;
16 }
17 };
18
19 vector<Edge> G[MAX];
20
21 struct node
22 {
23 int id,step;
24 node(int id,int step)
25 {
26 this->id=id;
27 this->step=step;
28 }
29 };
30
31 queue<node> q;
32 bool vis[MAX];
33 bool BFS(int k)
34 {
35 while(!q.empty())
36 q.pop();
37
38 memset(vis,0,sizeof vis);
39
40 q.push(node(1,0));
41 vis[1]=true;
42 while(!q.empty())
43 {
44 node now=q.front();
45 q.pop();
46
47 int u=now.id;
48 if(u==n)
49 return now.step<=n;
50
51 for(int i=0;i<G[u].size();i++)
52 {
53 Edge e=G[u][i];
54
55 if(vis[e.to]||e.w>k)
56 continue;
57
58 vis[e.to]=true;
59
60 q.push(node(e.to,now.step+1));
61 }
62 }
63 return false;
64 }
65
66 int main()
67 {
68 while(~scanf("%d%d",&n,&m))
69 {
70 int l=1,r=1;
71 for(int i=0;i<m;i++)
72 {
73 int a,b,c;
74 scanf("%d%d%d",&a,&b,&c);
75 r=max(r,c+1);
76 G[a].push_back(Edge(b,c));
77 G[b].push_back(Edge(a,c));
78 }
79
80 int ans=0;
81
82 while(l<=r)
83 {
84 int mid=(l+r)/2;
85 if(BFS(mid))
86 {
87 ans=mid;
88 r=mid-1;
89 }
90 else
91 l=mid+1;
92 }
93
94 printf("%d\n",ans);
95 }
96 return 0;
97 }