P1111 修复公路 (并查集,排序)

洛谷链接:https://www.luogu.com.cn/problem/P1111

P1111 修复公路

题目背景

A 地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车。政府派人修复这些公路。

题目描述

给出 A 地区的村庄数 \(N\),和公路数 \(M\),公路是双向的。并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路。问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路)。

输入格式

\(1\) 行两个正整数 \(N,M\)

下面 \(M\) 行,每行 \(3\) 个正整数 \(x,y,t\),告诉你这条公路连着 \(x,y\) 两个村庄,在时间 \(t\) 时能修复完成这条公路。

输出格式

如果全部公路修复完毕仍然存在两个村庄无法通车,则输出 \(-1\),否则输出最早什么时候任意两个村庄能够通车。

输入输出样例 #1

输入 #1

4 4
1 2 6
1 3 4
1 4 5
4 2 3

输出 #1

5

说明/提示

\(1\leq x, y\leq N \le 10 ^ 3\)\(1\leq M, t \le 10 ^ 5\)

思路

先对所有的公路按照时间从小到大排序,接下来依次连接,如果连接的公路顶点相同则跳过,每次连接更新ans
,对所有的公路进行操作过依次后,检查一遍所有村庄节点,如果存在村庄的顶点不同,则说明所有公路的公路相连,无法将所有的村庄连接起来

题解

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int n,m;
int ans = 0;
struct way
{
    int st,to,t;
}w[N];

int father[N];
bool cmp(way a,way b)
{

    return a.t<b.t;
}

void init() {
    for (int i = 1; i <= n; ++i) {
        father[i] = i;
    }
}

int find(int u) {
    return u == father[u] ? u : father[u]=find(father[u]);
}

bool isSame(int u, int v) {
   u = find(u);
   v = find(v);
   return u == v;
}
void join(int u, int v) {
    u = find(u);
    v = find(v);
    if (u == v) return ;
    father[v] = u;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    for(int i=0;i<m;i++)cin>>w[i].st>>w[i].to>>w[i].t;
    sort(w,w+m,cmp);
    init();
    // for(int i=0;i<m;i++)cout<<w[i].t<<endl;
    for(int i=0;i<m;i++)
    {
        if(isSame(w[i].st,w[i].to)==0)
        {
            join(w[i].st,w[i].to);
            ans = max(ans,w[i].t);
        }
    }
    for(int i=2;i<=n;i++)
    {
        if(isSame(1,i)==0)
        {
            cout<<-1<<endl;
            return 0;
        }
    }
    cout<<ans<<endl;
    return 0;
}
posted @ 2025-05-28 13:28  屈臣  阅读(48)  评论(0)    收藏  举报