题目描述

在遥远的S星系中一共有N个星球,编号为1…N。其中的一些星球决定组成联盟,以方便相互间的交流。但是,组成
联盟的首要条件就是交通条件。初始时,在这N个星球间有M条太空隧道。每条太空隧道连接两个星球,使得它们能
够相互到达。若两个星球属于同一个联盟,则必须存在一条环形线路经过这两个星球,即两个星球间存在两条没有
公共隧道的路径。为了壮大联盟的队伍,这些星球将建设P条新的太空隧道。这P条新隧道将按顺序依次建成。一条
新轨道建成后,可能会使一些星球属于同一个联盟。你的任务是计算出,在一条新隧道建设完毕后,判断这条新轨
道连接的两个星球是否属于同一个联盟,如果属于同一个联盟就计算出这个联盟中有多少个星球。

输入

第1行三个整数N,M和P,分别表示总星球数,初始时太空隧道的数目和即将建设的轨道数目。
第2至第M+1行,每行两个整数,表示初始时的每条太空隧道连接的两个星球编号。
第M+2行至第M+P+1行,每行两个整数,表示新建的太空隧道连接的两个星球编号。
这些太空隧道按照输入的顺序依次建成。
1≤N,M,P≤200000

输出

输出共P行。
如果这条新的太空隧道连接的两个星球属于同一个联盟,就输出一个整数,表示这两个星球所在联盟的星球数。
如果这条新的太空隧道连接的两个星球不属于同一个联盟,就输出"No"(不含引号)。

样例输入

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

样例输出

No
3
2
5

提示

BZOJ2959弱化版

如果两个星球属于同一个联盟,那么他们就属于一个点双,用LCT维护点双缩点后的树,用两个并查集分别维护每个点属于哪个点双及点之间连通性,加边时分两种情况讨论即可。具体操作参见BZOJ2959。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pr pair<int,int>
#define ll long long
using namespace std;
int g[200010];
int fa[200010];
int f[200010];
int s[200010][2];
int sum[200010];
int st[200010];
int r[200010];
int size[200010];
int n,m,p;
int opt;
int x,y;
int find(int x)
{
if(fa[x]==x)
{
return x;
}
return fa[x]=find(fa[x]);
}
int judge(int x)
{
if(g[x]==x)
{
return x;
}
return g[x]=judge(g[x]);
}
int is_root(int rt)
{
return rt!=s[find(f[rt])][0]&&rt!=s[find(f[rt])][1];
}
int get(int rt)
{
return rt==s[find(f[rt])][1];
}
void pushup(int rt)
{
sum[rt]=sum[s[rt][0]]+sum[s[rt][1]]+size[rt];
}
void pushdown(int rt)
{
if(r[rt])
{
swap(s[rt][0],s[rt][1]);
r[s[rt][0]]^=1;
r[s[rt][1]]^=1;
r[rt]^=1;
}
}
void rotate(int rt)
{
int fa=find(f[rt]);
int anc=find(f[fa]);
int k=get(rt);
if(!is_root(fa))
{
s[anc][get(fa)]=rt;
}
s[fa][k]=s[rt][k^1];
f[s[fa][k]]=fa;
s[rt][k^1]=fa;
f[fa]=rt;
f[rt]=anc;
pushup(fa);
pushup(rt);
}
void splay(int rt)
{
int top=0;
st[++top]=rt;
for(int i=rt;!is_root(i);i=find(f[i]))
{
st[++top]=find(f[i]);
}
for(int i=top;i>=1;i--)
{
pushdown(st[i]);
}
for(int fa;!is_root(rt);rotate(rt))
{
if(!is_root(fa=find(f[rt])))
{
rotate(get(fa)==get(rt)?fa:rt);
}
}
}
void access(int rt)
{
for(int x=0;rt;x=rt,rt=find(f[rt]))
{
splay(rt);
s[rt][1]=x;
pushup(rt);
}
}
void reverse(int rt)
{
access(rt);
splay(rt);
r[rt]^=1;
}
void link(int x,int y)
{
reverse(x);
f[x]=y;
g[g[x]]=g[y];
}
void dfs(int x,int rt)
{
fa[x]=rt;
if(s[x][0])
{
dfs(s[x][0],rt);
}
if(s[x][1])
{
dfs(s[x][1],rt);
}
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
for(int i=1;i<=n;i++)
{
fa[i]=g[i]=i;
size[i]=sum[i]=1;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
int fx=find(x);
int fy=find(y);
if(fx!=fy)
{
if(judge(fx)!=judge(fy))
{
link(fx,fy);
}
else
{
reverse(fx);
access(fy);
splay(fy);
size[fy]=sum[fy];
dfs(fy,fy);
s[fy][0]=0;
}
}
}
for(int i=1;i<=p;i++)
{
scanf("%d%d",&x,&y);
int fx=find(x);
int fy=find(y);
if(fx==fy)
{
reverse(fx);
access(fy);
splay(fy);
printf("%d\n",sum[fx]);
}
else if(judge(fx)!=judge(fy))
{
link(fx,fy);
printf("No\n");
}
else
{
reverse(fx);
access(fy);
splay(fy);
size[fy]=sum[fy];
dfs(fy,fy);
s[fy][0]=0;
printf("%d\n",sum[fy]);
}
}
}

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

  1. 【bzoj4998】星球联盟(并查集+边双)

    题面 传送门 题解 总算有自己的\(bzoj\)账号啦! 话说这题好像\(Scape\)去年暑假就讲过--然而我到现在才会-- \(LCT\)什么的跑得太慢了而且我也不会,所以这里是一个并查集的做法 ...

  2. BZOJ2959长跑——LCT+并查集(LCT动态维护边双连通分量)

    题目描述 某校开展了同学们喜闻乐见的阳光长跑活动.为了能“为祖国健康工作五十年”,同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动.一时间操场上熙熙攘攘,摩肩接踵,盛况空前. 为 ...

  3. BZOJ4229选择——LCT+并查集+离线(LCT动态维护边双连通分量)

    题目描述 现在,我想知道自己是否还有选择. 给定n个点m条边的无向图以及顺序发生的q个事件. 每个事件都属于下面两种之一: 1.删除某一条图上仍存在的边 2.询问是否存在两条边不相交的路径可以从点u出 ...

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

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

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

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

  6. 【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT

    题目描述 给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. $n\le 3\times 10^5$ ,$ ...

  7. bzoj 3669: [Noi2014]魔法森林(并查集+LCT)

    Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...

  8. 【bzoj2959】长跑 LCT+并查集

    题目描述 某校开展了同学们喜闻乐见的阳光长跑活动.为了能“为祖国健康工作五十年”,同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动.一时间操场上熙熙攘攘,摩肩接踵,盛况空前.为了 ...

  9. BZOJ 2959 长跑 (LCT+并查集)

    题面:BZOJ传送门 当成有向边做的发现过不去样例,改成无向边就忘了原来的思路.. 因为成环的点一定都能取到,我们把它们压成一个新点,权值为环上所有点的权值和 这样保证了图是一颗森林 每次询问转化为, ...

随机推荐

  1. Tensorflow[源码安装时bazel行为解析]

    0. 引言 通过源码方式安装,并进行一定程度的解读,有助于理解tensorflow源码,本文主要基于tensorflow v1.8源码,并借鉴于如何阅读TensorFlow源码. 首先,自然是需要去b ...

  2. 【Linux系统目录结构】

    登录系统后,在当前命令窗口下输入 ls / 你会看到 以下是对这些目录的解释: /bin bin是Binary的缩写.这个目录存放着最经常使用的命令. /boot 这里存放的是启动Linux时使用的一 ...

  3. win10 + VS2010 + OpenCV2.4.10重编译OpenCV开发环境搭建

    win10 + VS2010 + OpenCV2.4.10重编译OpenCV开发环境搭建 重编译的优点:能够调试的时候看OpenCV的源码. 重编译要得到的东西:Debug版本号和Release版本号 ...

  4. linux应用编程之进程间同步

    一.描述 在操作系统中,异步并发执行环境下的一组进程,因为相互制约关系,进而互相发送消息.互相合作.互相等待,使得各进程按一定的顺序和速度执行,称为进程间的同步.具有同步关系的一组并发进程,称为合作进 ...

  5. Data Partitioning Guidance

    在很多大规模的解决方案中,数据都是分成单独的分区,可以分别进行管理和访问的.而分割数据的策略必须仔细的斟酌才能够最大限度的提高效益,同时最大限度的减少不利影响.数据的分区可以极大的提升可扩展性,降低争 ...

  6. Windows环境下实现Consul服务注册和服务发现

    1.首先从官方网站下载Consul,因为我们是使用的Windows系统,所以选择windows版本 https://www.consul.io/downloads.html 2.可以用开发者模式来启动 ...

  7. 用PHP山寨一款软件

    什么是我国软件工程师引以为豪的能力?山寨.山寨,山寨! 我国程序员的山寨能力是世界一流的.这一点在世界范围内令人闻风丧胆.世界上根本就找不到一款我国工程师不能山寨的软件. 今天,锋哥教大家来山寨一款软 ...

  8. 本地开发环境搭建(windows)

    一.虚拟器安装 1.概念 ・为什么要搭建搭建模拟环境 在租借服务器前用手中的PC模拟一个服务器的环境,可以打包与团队人员分享 ・什么是Vagrant https://segmentfault.com/ ...

  9. JSON.NET VS BinaryFormatter 性能

    近期有个性能调优工作.通过dottrace 分析,发现几处问题,其中json.net 在序列化和反序列化的时候也比较耗性能,所以考虑能不能通过其它序列化方式来提高性能. 1 object 序列化代码 ...

  10. 最小生成树模板题POJ - 1287-prim+kruskal

    POJ - 1287超级模板题 大概意思就是点的编号从1到N,会给你m条边,可能两个点之间有多条边这种情况,求最小生成树总长度? 这题就不解释了,总结就算,prim是类似dijkstra,从第一个点出 ...