蓝桥杯 国王的烦恼 (并查集)

Posted 小坏蛋_千千

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯 国王的烦恼 (并查集)相关的知识,希望对你有一定的参考价值。

问题描述

C国由n个小岛组成,为了方便小岛之间联络,C国在小岛间建立了m座大桥,每座大桥连接两座小岛。两个小岛间可能存在多座桥连接。然而,由于海水冲刷,有一些大桥面临着不能使用的危险。

如果两个小岛间的所有大桥都不能使用,则这两座小岛就不能直接到达了。然而,只要这两座小岛的居民能通过其他的桥或者其他的小岛互相到达,他们就会安然无事。但是,如果前一天两个小岛之间还有方法可以到达,后一天却不能到达了,居民们就会一起抗议。

现在C国的国王已经知道了每座桥能使用的天数,超过这个天数就不能使用了。现在他想知道居民们会有多少天进行抗议。

 

输入格式

输入的第一行包含两个整数n, m,分别表示小岛的个数和桥的数量。

接下来m行,每行三个整数a, b, t,分别表示该座桥连接a号和b号两个小岛,能使用t天。小岛的编号从1开始递增。

 

输出格式

输出一个整数,表示居民们会抗议的天数。

 

样例输入

4 4
1 2 2
1 3 2
2 3 1
3 4 3

 

样例输出

2

 

思路

考虑用并查集来维护所有岛屿之间的连通性,我们可以对所有的边按照使用期从大到小排序(反向思考),然后遍历枚举。

在枚举的过程中,若一条边的两端不在同一个连通块,则说明新增的这一个桥梁会引起群众的抗议,此时 ans++

注意同一天的多次群众抗议我们只统计一次。

 

AC 代码

#include <iostream>
#include <algorithm>
#include <string.h>
#include <queue>
#include <set>
#include <map>
#include <stack>
#define inf 0x7f7f7f
#define IO                       \\
    ios::sync_with_stdio(false); \\
    cin.tie(0);                  \\
    cout.tie(0);
using namespace std;
const int maxn = 1e6 + 10;
typedef long long LL;
int n,m;

struct node
    int to;
    int from;
    int cost;
    int next;
    friend bool operator<(const node &x,const node &y)
        return x.cost > y.cost;
    
edge[maxn];
int head[maxn],tot;
int fa[maxn],rk[maxn];

void init()
    memset(head,-1,sizeof(head));
    tot = 0;


void addedge(int u,int v,int cost)
    edge[tot].to = v;
    edge[tot].from = u;
    edge[tot].cost = cost;
    edge[tot].next = head[u];
    head[u] = tot ++;


int find_set(int x)
    if(x != fa[x])
        fa[x] = find_set(fa[x]);
    return fa[x];


bool union_set(int x,int y)
    x = find_set(x);
    y = find_set(y);
    if(x==y)return false;
    if(rk[x]>rk[y])
        fa[y] = x;
    else
        fa[x] = y;
        if(rk[x]==rk[y])
            ++rk[y];
    
    return true;


void solve()
    memset(rk,0,sizeof(rk));
    for(int i=1;i<maxn;i++)
        fa[i] = i;
    int ans = 0,now = -1;
    for(int i=0;i<tot;i++)
        int from = edge[i].from;
        int to = edge[i].to;
        bool flag = union_set(from,to);
        if(flag && now != edge[i].cost)
            ++ans;
            now = edge[i].cost; 
        
    
    cout<<ans<<endl;


int main()
    IO;
    init();
    cin>>n>>m;
    for(int i=0;i<m;i++)
        int u,v,cost;
        cin>>u>>v>>cost;
        addedge(u,v,cost);
    
    sort(edge,edge+tot);
    solve();
    return 0;

以上是关于蓝桥杯 国王的烦恼 (并查集)的主要内容,如果未能解决你的问题,请参考以下文章

nyoj925_国王的烦恼_并查集

蓝桥杯 修改数组 python (并查集)

冲击蓝桥杯-并查集,前缀和,字符串

第四届蓝桥杯真题 连号区间

蓝桥杯冲刺并查集专题

简洁而优美的结构 - 并查集 | 一文吃透 “带权并查集” 不同应用场景 | “手撕” 蓝桥杯A组J题 - 推导部分和