2020牛客暑期多校训练营(第三场)G、Operating on a Graph(并查集)

这是一篇关于使用并查集解决图论问题的博客,主要介绍了如何处理图中节点集合的变化。在一系列操作中,某节点可以吸收与其相邻且不在同一集合的节点,最终确定每个点所属的集合。题解部分讲解了利用链表优化的并查集实现,能以O(1)的时间复杂度合并链表。
摘要由CSDN通过智能技术生成

题目链接

题面:
在这里插入图片描述
题意:
给了一张图,一开始每个点在自己的集合中,如果存在一条边,其两个端点在不同集合中,我们认为这两个集合相邻。
每次选取一个点,若该点在自己的集合中,将该集合所有相邻的集合中间的点并入该集合中
输出q此操作后每个点所在的集合。

化简题意:
给一个 n 个点的 Graph,第 i 个点一刚开始是第 I 种颜色,接着有 k 次操作,第 i 次操作有个参数 oi 代表颜色 oi 会侵略所有和自己相邻的颜色,于是所有和 oi 相邻的颜色全都变成 oi (若已没有颜色oi 已被侵略,则该次操作无效),求最终每个点的颜色。

题解:
我们用并查集维护每个点所属的集合。
用链表维护每个集合有可能往外扩展的点,合并时,遍历这些有可能往外扩展的点,看看哪一些可以扩展,同时维护链表。链表的splice可以O(1)合并两个链表。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#include<list>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
//#define len(x)  (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
using namespace std;

const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=998244353;
const double eps=1e-1;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=800100;
const int maxp=1100;
const int maxm=500100;
const int up=100000;

int head[maxn],ver[maxn<<1],nt[maxn<<1],tot=1;
int f[maxn];
list<int>li[maxn];
vector<int>vc;

void add(int x,int y)
{
    ver[++tot]=y,nt[tot]=head[x],head[x]=tot;
}

int fi(int x)
{
    if(f[x]!=x)
        f[x]=fi(f[x]);
    return f[x];
}

int main(void)
{
    int tt;
    scanf("%d",&tt);
    while(tt--)
    {
        int n,m,x,y;
        scanf("%d%d",&n,&m);

        tot=1;
        for(int i=1;i<=n;i++)
        {
            head[i]=0;
            li[i].clear();
            li[i].pb(i);
            f[i]=i;
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            x++,y++;
            add(x,y);
            add(y,x);
        }
        int q;
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            scanf("%d",&x);
            x++;
            if(x!=fi(x)) continue;
            vc.clear();
            for(auto it=li[x].begin();it!=li[x].end();it++)
            {
                for(int j=head[*it];j;j=nt[j])
                {
                    int y=fi(ver[j]);
                    if(y==x) continue;
                    f[y]=x;
                    vc.pb(y);
                }
            }
            li[x].clear();
            for(int j=0;j<vc.size();j++)
            {
                if(!li[vc[j]].empty())
                    li[x].splice(li[x].end(),li[vc[j]]);
            }
        }
        for(int i=1;i<=n;i++)
            printf("%d ",fi(i)-1);
        putchar('\n');

    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
水利改革发展 中国政府高度重视水利建设,将水利作为国家基础设施建设的优先领域。政策文件强调了防洪抗旱、水资源管理、水环境保护和水生态修复等方面的全面要求,推动了水利信息化的发展。 智慧水利建设目标 智慧水利的建设目标是通过数据共享、应用惠民、应急预警等手段,打破信息孤岛,提升应急抢险协作能力,加强水利数据在惠民信息化方面的应用。同时,提出了共享联动化、解决信息安全问题、提高水利信息科技创新能力等目标。 智慧水利建设模式 智慧水利的建设模式包括构建统一平台、数据中心、信息整合平台、决策支持系统等,以实现水利、海洋、环保等政府部门和公众的信息共享和服务。此外,还包括了云计算虚拟化、网络传输、采集工程等多个方面的技术应用。 智慧水利应用实例 智慧水利的应用实例包括视频水文工程监控、多要素一体化检测设备、汛情预警智能联动、三防决策指挥、河长综合信息展示等。这些应用通过集成GIS、互联网地图服务、物联网设备等技术,实现了对水利设施的实时监控、数据分析和应急响应。 成功案例与展望 智慧水利的成功案例展示了通过视频监控、预警信息发布、移动办公信息APP等技术,有效提升了灾害应对能力、水资源管理和河长制的实施效果。这些案例表明,智慧水利的建设不仅提高了水利管理的效率和水平,也为未来的水利信息化发展提供了方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值