即要求动态维护边双。出现环时将路径上的点合并即可。LCT维护。具体地,加边成环时makeroot+access+splay一套把这段路径提出来,暴力dfs修改并查集祖先,并将这部分与根断开,视为删除这些点,以后就以并查集中的祖先代替这些点。access时更新每个点的父亲。注意由于之前的删点操作,判断是否连通需要另开一个并查集而不能findroot。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 200010
#define lson tree[k].ch[0]
#define rson tree[k].ch[1]
#define lself tree[tree[k].fa].ch[0]
#define rself tree[tree[k].fa].ch[1]
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,q,fa[N],fa2[N],size[N];
struct data{int ch[],fa,rev;
}tree[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int find2(int x){return fa2[x]==x?x:fa2[x]=find2(fa2[x]);}
void rev(int k){if (k) swap(lson,rson),tree[k].rev^=;}
void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=;}
int whichson(int k){return rself==k;}
bool isroot(int k){return lself!=k&&rself!=k;}
void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);}
void move(int k)
{
int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k);
if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf;
tree[fa].ch[p]=tree[k].ch[!p],tree[tree[k].ch[!p]].fa=fa;
tree[k].ch[!p]=fa,tree[fa].fa=k;
}
void splay(int k)
{
push(k);
while (!isroot(k))
{
int fa=tree[k].fa;
if (!isroot(fa))
if (whichson(fa)^whichson(k)) move(k);
else move(fa);
move(k);
}
}
void access(int k){for (int t=;k;t=k,k=tree[k].fa=find(tree[k].fa)) splay(k),tree[k].ch[]=t;}
void makeroot(int k){access(k),splay(k),rev(k);}
void link(int x,int y){makeroot(x),tree[x].fa=y,fa2[find2(x)]=find2(y);}
void dfs(int k,int x)
{
if (!k) return;
if (find(k)!=x) size[x]+=size[find(k)],fa[find(k)]=x;
dfs(lson,x),dfs(rson,x);
}
void addedge(int x,int y)
{
if (find2(x)!=find2(y)) link(x,y);
else
{
makeroot(x),access(y),splay(y);
dfs(tree[y].ch[],y);tree[y].ch[]=;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4998.in","r",stdin);
freopen("bzoj4998.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read(),q=read();
for (int i=;i<=n;i++) fa[i]=i,fa2[i]=i,size[i]=;
for (int i=;i<=m;i++)
{
int x=find(read()),y=find(read());
if (x!=y) addedge(x,y);
}
for (int i=;i<=q;i++)
{
int x=find(read()),y=find(read());
if (x!=y) addedge(x,y);
if (find(x)==find(y)) printf("%d\n",size[fa[x]]);
else printf("No\n");
}
return ;
}

BZOJ4998 星球联盟(LCT+双连通分量+并查集)的更多相关文章

  1. BZOJ 2959: 长跑 [lct 双连通分量 并查集]

    2959: 长跑 题意:字词加入边,修改点权,询问两点间走一条路径的最大点权和.不一定是树 不是树

  2. BZOJ4998星球联盟——LCT+并查集(LCT动态维护边双连通分量)

    题目描述 在遥远的S星系中一共有N个星球,编号为1…N.其中的一些星球决定组成联盟,以方便相互间的交流.但是,组成 联盟的首要条件就是交通条件.初始时,在这N个星球间有M条太空隧道.每条太空隧道连接两 ...

  3. bzoj4998 星球联盟 LCT + 并查集

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4998 题解 根据题意,就是要动态维护点双,求出一个点双的权值和. 所以这道题就是和 bzoj2 ...

  4. bzoj4998 星球联盟

    bzoj4998 星球联盟 原题链接 题解 先按照输入顺序建一棵树(森林),然后用一个并查集维护联盟的关系,对于不是树上的边\(a-b\),就把\(a-lca(a,b),b-lca(a,b)\)全部合 ...

  5. 【bzoj4998】星球联盟 LCT+并查集

    题目描述 在遥远的S星系中一共有N个星球,编号为1…N.其中的一些星球决定组成联盟,以方便相互间的交流.但是,组成联盟的首要条件就是交通条件.初始时,在这N个星球间有M条太空隧道.每条太空隧道连接两个 ...

  6. bzoj4998: 星球联盟(link-cut-tree)

    题面 bzoj 题解 bzoj2959: 长跑的弱化版 产生了环就并查集维护一下 Code #include<bits/stdc++.h> #define LL long long #de ...

  7. HDU 3749 Financial Crisis (点双连通+并查集)

    <题目连接> 题目大意: 给你一个(保证输入无重边,无自环)无向图,然后有下面Q条询问,每条询问为:问你u点与v点之间有几条(除了首尾两点外,其他点不重复)的路径.如果有0条或1条输出0或 ...

  8. BZOJ 1854: [Scoi2010]游戏 [连通分量 | 并查集 | 二分图匹配]

    题意: 有$n \le 10^6$中物品,每种两个权值$\le 10^4$只能选一个,使得选出的所有权值从1递增,最大递增到多少 一开始想了一个奇怪的规定流量网络流+二分答案做法...然而我还不知道怎 ...

  9. 图-连通分量-DFS-并查集-695. 岛屿的最大面积

    2020-03-15 16:41:45 问题描述: 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二 ...

随机推荐

  1. Potree学习总结

    一.      简介 基于Web端的三维模型展示,这里仅介绍Three.js和Potree. Three.js 是一款基于WebGL的运行在浏览器中的 3D 开源引擎,用它创建各种三维场景.它类似于M ...

  2. rman的基于窗口的备份保留策略学习

    例如: rman>configure retention policy to recovery window of 7 days; 那么就是说,至少要使得保留下来的备份,可以支持恢复到从当前回溯 ...

  3. C# 调用C++ dll 返回char*调用方式(StringBuilder乱码)

    // CDLLDemo.cpp : 定义 DLL 应用程序的导出函数. // #include "stdafx.h" #include "string.h" # ...

  4. Appium 安卓计算器demo

    package testProject; import org.openqa.selenium.*; import org.openqa.selenium.remote.DesiredCapabili ...

  5. 观察者模式——Java实例

    一.定义 观察者模式(有时又被称为模型-视图(View)模式.源-收听者(Listener)模式或从属者模式)是软件设计模式的一种.观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个 ...

  6. Hexo博客 云服务器搭建

    下载nodejs: https://nodejs.org/dist/v10.15.1/node-v10.15.1-linux-x64.tar.xz 解压:tar zxv       解压后编译:   ...

  7. ThinkPHP - 6 - 学习笔记(2015.5.4)

    解决:OneThink 站点无法被友言uyan后台识别 打开友言uyan插件功能,但OneThink站点无法被友言uyan后台检测到.页面生成的uyan代码为: <!-- UY BEGIN -- ...

  8. WeakHashMap介绍

    WeakHashMap简介 WeakHashMap 继承于AbstractMap,实现了Map接口.    和HashMap一样,WeakHashMap 也是一个散列表,它存储的内容也是键值对(key ...

  9. [笔记] postgresql 流复制(streaming replication)

    基本环境说明: os:FreeBSD 9.3 postgresql version: master:192.168.56.101 standby:192.168.56.102 安装过程略,基于pkg包 ...

  10. High School: Become Human(数学思维)

    Year 2118. Androids are in mass production for decades now, and they do all the work for humans. But ...