luoguP5227 [AHOI2013]连通图
2024-10-19 00:56:37
题意
虽然没用线段树,但是仍然是线段树分治的思想。
考虑分治询问序列,假设当前在\([l,r]\),我们将\([1,l-1]\)和\([r+1,Q]\)的与\([l,r]\)内不重复的边都连上了。
先将\([mid+1,r]\)中与\([l,mid]\)不重复的边都连上,之后递归\([l,mid]\),再将之前的操作撤销,将\([l,mid+1]\)中与\([mid+1,r]\)不重复的边都连上,之后递归\([mid+1,r]\)。
发现当低递归到\([l,l]\)时,整个并查集正好是第\(l\)组询问的图的状态。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=2*1e5+10;
const int maxQ=1e5+10;
int n,m,Q,top;
int fa[maxn],size[maxn];
bool ans[maxn],check[maxm];
struct Edge{int u,v;}E[maxm];
struct node{int x,y,sizey;}sta[maxQ];
vector<int>edge[maxQ];
inline int read()
{
char c=getchar();int res=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
return res*f;
}
int find(int x){return fa[x]==x?x:find(fa[x]);}
inline void merge(int u,int v,bool op)
{
int x=find(u),y=find(v);
if(x==y)return;
if(size[x]>size[y])swap(x,y);
if(op)sta[++top]=(node){x,y,size[y]};
fa[x]=y;size[y]+=size[x];
}
inline void cut(int id)
{
int x=sta[id].x,y=sta[id].y;
fa[x]=x;size[y]=sta[id].sizey;
}
void solve(int l,int r)
{
if(l==r){ans[l]=(size[find(1)]==n);return;}
int now=top,mid=(l+r)>>1;
for(int i=mid+1;i<=r;i++)
for(unsigned int j=0;j<edge[i].size();j++)
check[edge[i][j]]=1;
for(int i=l;i<=mid;i++)
for(unsigned int j=0;j<edge[i].size();j++)
check[edge[i][j]]=0;
for(int i=mid+1;i<=r;i++)
for(unsigned int j=0;j<edge[i].size();j++)
if(check[edge[i][j]])merge(E[edge[i][j]].u,E[edge[i][j]].v,1);
solve(l,mid);
while(top>now)cut(top),top--;
for(int i=l;i<=mid;i++)
for(unsigned int j=0;j<edge[i].size();j++)
check[edge[i][j]]=1;
for(int i=mid+1;i<=r;i++)
for(unsigned int j=0;j<edge[i].size();j++)
check[edge[i][j]]=0;
for(int i=l;i<=mid;i++)
for(unsigned int j=0;j<edge[i].size();j++)
if(check[edge[i][j]])merge(E[edge[i][j]].u,E[edge[i][j]].v,1);
solve(mid+1,r);
while(top>now)cut(top),top--;
for(int i=l;i<=mid;i++)
for(unsigned int j=0;j<edge[i].size();j++)
check[edge[i][j]]=0;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)fa[i]=i,size[i]=1;
for(int i=1;i<=m;i++)E[i].u=read(),E[i].v=read();
Q=read();
for(int i=1;i<=Q;i++)
{
int k=read(),id;
while(k--)id=read(),edge[i].push_back(id);
}
for(int i=1;i<=n;i++)fa[i]=i,size[i]=1;
for(int i=1;i<=Q;i++)
for(unsigned int j=0;j<edge[i].size();j++)
check[edge[i][j]]=1;
for(int i=1;i<=m;i++)if(!check[i])merge(E[i].u,E[i].v,0);
solve(1,Q);
for(int i=1;i<=Q;i++)puts(ans[i]?"Connected":"Disconnected");
return 0;
}
最新文章
- .Net 搭建 RESTful
- Js实现string.format
- Web应用程序的自动化测试库-FluentAutomation
- BulkyCopy .Net
- FibonacciSequence
- Android 抗锯齿的两种方法
- 【读书笔记】.Net并行编程(三)---并行集合
- 阿里云ecs Linux平台安装mongodb数据库
- Action接收页面传来的参数方法
- Spark Programming--Actions II
- LinearLayout属性baselineAligned的作用及baseline
- MySQL基本概念
- 不安装Oracle客户端远程连接Orcale数据库
- Struct2 拦截器
- CSS——(1)基础
- 图论(网络流,二分图最小点权覆盖):POJ 2125 Destroying The Graph
- Android--Toast时间
- Ios 该图显示其出现的相关问题定义UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:&;#39;
- java可访问修饰符
- 使用SpringSecurity保护你的Eureka.
热门文章
- 201871010112-梁丽珍《面向对象程序设计(java)》第十三周学习总结
- 浅谈python之利用pandas和openpyxl读取excel数据
- github 码云 chrome文件树形插件
- windows 10使用vscode进行远程代码开发 | tutorial to use vscode for remote development using ssh on windows
- Java正则表达式验证IP,邮箱,电话
- PHP判断设备访问来源
- Http Header的Transfer-Encoding
- webpack基本使用
- Python爬取知乎上搞笑视频,一顿爆笑送给大家
- Java生鲜电商平台-深入订单拆单架构与实战