[Ahoi2013]连通图

 2023-09-05 阅读 75 评论 0

摘要:Description Input Output Sample Input 4 5 1 2 2 3 3 4 4 1 2 4 3 1 5 2 2 3 2 1 2 Sample Output Connected Disconnected Connected HINT N<=100000N<=100000 M<=200000M<=200000 K<=100000K<=100000 Source 思路 cdq分治

Description

pps

Input

pps

Output

pps

Sample Input

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

Sample Output

Connected
Disconnected
Connected

HINT

N<=100000N<=100000 M<=200000M<=200000 K<=100000K<=100000

Source

思路

cdq分治,用并查集维护图,首先将任何询问都没有涉及到的边都添加到并查集中;
对于分治的一个区间的询问:
1. 首先将右区间有左区间没有的边添加到并查集中;
2. 递归处理左区间;
3. 还原并查集到递归这个区间的初始状态;
4. 将左区间有右区间没有的边添加到并查集中;
5. 递归处理右区间;
6. 同3
并查集可以用按秩合并。

代码

#include <cstdio>const int maxn=100000;
const int maxm=1000000;template<typename t>
struct stack
{t s[maxn+10];int head;inline int push(t x){s[++head]=x;return 0;}inline int pop(){--head;return 0;   }inline t top(){return s[head];}inline int size(){return head;}
};struct data
{int num,pr,t;
};inline data make_data(int num_,int pr_,int t_)
{data res;res.num=num_;res.pr=pr_;res.t=t_;return res;
}int n,tt;struct union_find_set
{int fa[maxn+10],h[maxn+10],cnt;stack<data> st;inline int find(int x){return fa[x]?find(fa[x]):x;}inline int merge(int x,int y,int kind,int ti){x=find(x);y=find(y);if(x==y){return 1;}--cnt;if(h[x]>h[y]){fa[y]=x;if(kind){st.push(make_data(y,h[x],ti));}}else{fa[x]=y;if(kind){st.push(make_data(x,h[y],ti));}if(h[x]==h[y]){++h[y];}}return 0;}inline int split(int ti){while(st.size()){data d=st.top();if(d.t!=ti){return 0;}st.pop();h[fa[d.num]]=d.pr;fa[d.num]=0;++cnt;}return 0;}
};union_find_set s;
int m,k,c[maxm+10],q[maxm+10][4],line[maxm+10][2],ans[maxm+10];
int tmp[maxm+10];int solve(int l,int r)
{if(l==r){if(s.cnt==1){ans[l]=0;}else{ans[l]=1;}return 0;}++tt;int mid=(l+r)>>1;for(register int i=mid+1; i<=r; ++i){for(register int j=0; j<c[i]; ++j){tmp[q[i][j]]=1;}}for(register int i=l; i<=mid; ++i){for(register int j=0; j<c[i]; ++j){tmp[q[i][j]]=0;}}for(register int i=mid+1; i<=r; ++i){for(register int j=0; j<c[i]; ++j){if(tmp[q[i][j]]==1){s.merge(line[q[i][j]][0],line[q[i][j]][1],1,tt);}}}solve(l,mid);s.split(tt);for(register int i=l; i<=mid; ++i){for(register int j=0; j<c[i]; ++j){tmp[q[i][j]]=1;}}for(register int i=mid+1; i<=r; ++i){for(register int j=0; j<c[i]; ++j){tmp[q[i][j]]=0;}}for(register int i=l; i<=mid; ++i){for(register int j=0; j<c[i]; ++j){if(tmp[q[i][j]]==1){s.merge(line[q[i][j]][0],line[q[i][j]][1],1,tt);}}}solve(mid+1,r);s.split(tt);for(register int i=l; i<=mid; ++i){for(register int j=0; j<c[i]; ++j){tmp[q[i][j]]=0;}}--tt;return 0;
}int main()
{scanf("%d%d",&n,&m);for(register int i=1; i<=m; ++i){scanf("%d%d",&line[i][0],&line[i][1]);}scanf("%d",&k);for(register int i=1; i<=k; ++i){scanf("%d",&c[i]);for(register int j=0; j<c[i]; ++j){scanf("%d",&q[i][j]);}}s.cnt=n;for(register int i=1; i<=n; ++i){s.h[i]=1;}for(register int i=1; i<=k; ++i){for(register int j=0; j<c[i]; ++j){tmp[q[i][j]]=1;}}for(register int i=1; i<=m; ++i){if(!tmp[i]){s.merge(line[i][0],line[i][1],0,0);}}for(register int i=1; i<=k; ++i){for(register int j=0; j<c[i]; ++j){tmp[q[i][j]]=0;}}solve(1,k);for(register int i=1; i<=k; ++i){if(ans[i]){puts("Disconnected");}else{puts("Connected");}}return 0;
}

转载于:https://www.cnblogs.com/Canopus-wym/p/10376239.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/35.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息