题解:BISHI104 修复公路

题目链接

修复公路

题目描述

给定 个城市与 条双向公路,每条公路连接 并在时间 修复完成。求最早的时间使得任意两城市之间连通;若所有公路修复后仍不连通,输出

解题思路

按修复时间从小到大将公路排序,用并查集逐条合并。首次使所有城市处于同一连通块的时间即答案;若结束仍有多个连通块,则输出

代码

#include <bits/stdc++.h>
using namespace std;

struct DSU {
    int n; vector<int> fa, sz;
    DSU(int n): n(n), fa(n+1), sz(n+1,1) { iota(fa.begin(), fa.end(), 0); }
    int find(int x){ return fa[x]==x? x: fa[x]=find(fa[x]); }
    bool unite(int a,int b){ a=find(a); b=find(b); if(a==b) return false; if(sz[a]<sz[b]) swap(a,b); fa[b]=a; sz[a]+=sz[b]; return true; }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m; if(!(cin >> n >> m)) return 0;
    struct E{int u,v; long long t;};
    vector<E> es(m);
    for(int i=0;i<m;i++){ cin >> es[i].u >> es[i].v >> es[i].t; }
    sort(es.begin(), es.end(), [](const E& a, const E& b){ return a.t < b.t; });
    DSU dsu(n);
    int comps = n;
    for(auto &e: es){
        if(dsu.unite(e.u, e.v)){
            if(--comps == 1){ cout << e.t << '\n'; return 0; }
        }
    }
    cout << -1 << '\n';
    return 0;
}
import java.io.*;
import java.util.*;

public class Main {
    static class FastScanner {
        private final InputStream in; private final byte[] buf = new byte[1<<16];
        private int p=0,l=0; FastScanner(InputStream is){in=is;}
        private int read() throws IOException { if(p>=l){ l=in.read(buf); p=0; if(l<=0) return -1; } return buf[p++]; }
        int nextInt() throws IOException { int c; int s=1,x=0; do{c=read();}while(c<=32); if(c=='-'){s=-1;c=read();} while(c>32){ x=x*10+(c-'0'); c=read(); } return x*s; }
        long nextLong() throws IOException { int c; long s=1,x=0; do{c=read();}while(c<=32); if(c=='-'){s=-1;c=read();} while(c>32){ x=x*10+(c-'0'); c=read(); } return x*s; }
    }

    static class DSU {
        int[] fa, sz;
        DSU(int n){ fa=new int[n+1]; sz=new int[n+1]; for(int i=0;i<=n;i++){ fa[i]=i; sz[i]=1; } }
        int find(int x){ return fa[x]==x? x: (fa[x]=find(fa[x])); }
        boolean unite(int a,int b){ a=find(a); b=find(b); if(a==b) return false; if(sz[a]<sz[b]){int t=a;a=b;b=t;} fa[b]=a; sz[a]+=sz[b]; return true; }
    }

    static class E { int u,v; long t; }

    public static void main(String[] args) throws Exception {
        FastScanner fs = new FastScanner(System.in);
        int n = fs.nextInt();
        int m = fs.nextInt();
        E[] es = new E[m];
        for(int i=0;i<m;i++){ E e=new E(); e.u=fs.nextInt(); e.v=fs.nextInt(); e.t=fs.nextLong(); es[i]=e; }
        Arrays.sort(es, (a,b)-> Long.compare(a.t, b.t));
        DSU dsu = new DSU(n);
        int comps = n;
        for(E e: es){
            if(dsu.unite(e.u, e.v)){
                if(--comps == 1){ System.out.println(e.t); return; }
            }
        }
        System.out.println(-1);
    }
}
import sys

data = sys.stdin.buffer.read().split()
it = iter(data)
n = int(next(it)); m = int(next(it))
edges = []
for _ in range(m):
    u = int(next(it)); v = int(next(it)); t = int(next(it))
    edges.append((t, u, v))
edges.sort()

fa = list(range(n+1))
sz = [1]*(n+1)
def find(x: int) -> int:
    while fa[x] != x:
        fa[x] = fa[fa[x]]
        x = fa[x]
    return x

comps = n
for t,u,v in edges:
    ru, rv = find(u), find(v)
    if ru != rv:
        if sz[ru] < sz[rv]:
            ru, rv = rv, ru
        fa[rv] = ru
        sz[ru] += sz[rv]
        comps -= 1
        if comps == 1:
            print(t)
            break
else:
    print(-1)

算法及复杂度

  • 算法:按修复时间排序 + 并查集合并;首次连通即答案
  • 时间复杂度:
  • 空间复杂度: