洛谷 P1111 修复公路(最小生成树)

嗯...

题目链接:https://www.luogu.org/problemnew/show/P1111

 

这道题的关键是读懂题:

首先根据题中的一些扎眼的字眼我们可以判断这是一道用最小生成树来做的题...

 

但是注意一个东西:施工时是同时性的!!!!

所以,施工时间应该是要施工的道路中所需时间的最大值...

换句话说,就是要求我们合并时最大的边权,我们只需用一个ans来维护就行

 

其次,如何判断是否存在“全部公路修复完毕仍然存在两个村庄无法通车”的情况,这就要用到了生成树的概念:

在一幅图中将所有n个点连接起来的n-1条边所形成的树

而num我们存储的即为边的数量,将它与n-1进行比较即可

 

思路:

在最小生成树的模板的基础上进行修改,在合并x点和y点的时候用num记录所修的道路数量,用ans记录边权的最大值,上面已经说过,边权最大值即为所需的时间...最后输出时将num与n-1进行比较

 

AC代码:

 1 #include
 2 #include
 3 #include
 4 
 5 using namespace std;
 6 
 7 int f[10005], ans;
 8 int num;
 9 
10 struct node{
11     int x, y, l;
12 } a[100005];
13 
14 inline int cmp(node i, node j){
15     return i.l < j.l;
16 }
17 
18 inline int find(int x){
19     if(f[x] != x)
20         f[x] = find(f[x]);
21     return f[x];
22 }
23 
24 int main(){
25     int n, m;
26     scanf("%d%d", &n, &m);
27     for(int i = 1; i <= n; i++)
28         f[i] = i;
29     for(int i = 1; i <= m; i++){
30         scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].l);
31     }
32     sort(a+1, a+m+1, cmp);
33     for(int i = 1; i <= m; i++){
34         int r1 = find(a[i].x);
35         int r2 = find(a[i].y);
36         if(r1 != r2){
37             f[r1] = r2;
38             num++;//道路数量 
39             ans = max(ans, a[i].l);//时间 
40         }
41     }
42     if(num >= n - 1) printf("%d", ans);
43     else printf("-1");
44     return 0;
45 }
AC代码

 

转载于:https://www.cnblogs.com/New-ljx/p/10779712.html

你可能感兴趣的:(洛谷 P1111 修复公路(最小生成树))