您的位置:首页 > 其它

BZOJ3237: [Ahoi2013]连通图

2015-12-17 13:48 239 查看
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3237

cdq分治+缩点。

可以每次处理的时候把除l~r之外的边的端点都连起来。然后去跑cdq分治。

当l==r的时候让那些修改边不连然后跑一边并查集。

#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 200500
using namespace std;
struct data{int x,y,id,k,b;
}a[21][maxn];
int b[maxn][5];
int fa[maxn],np[maxn],pos[maxn],n,m,Q;
int read(){
int x=0,f=1; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int find(int x){
if (fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void cdq(int dep,int l,int r,int n,int m){
rep(i,1,m){
data &c=a[dep][i],&c2=a[dep-1][i];
c=(data){c2.x,c2.y,c2.id,0,0};
pos[c2.id]=i;
}
if (l==r){
rep(i,1,b[l][0]) a[dep][pos[b[l][i]]].b=1;
rep(i,1,n) fa[i]=i;
int cnt=0;
rep(i,1,m) if (a[dep][i].b!=1) {
data c=a[dep][i];
int x=find(c.x),y=find(c.y);
if (x!=y) fa[x]=y,cnt++;
}
if (cnt==n-1) puts("Connected");
else puts("Disconnected");
return;
}
rep(i,l,r) rep(j,1,b[i][0]) a[dep][pos[b[i][j]]].k=1;
rep(i,1,n) fa[i]=i;
rep(i,1,m) if (a[dep][i].k==0){
data &c=a[dep][i];
int x=find(c.x),y=find(c.y);
if (x!=y) fa[x]=y;
}
rep(i,1,n) np[i]=0;
int nn=0,nm=0;
rep(i,1,n) if (!np[find(i)]) np[find(i)]=++nn;
rep(i,1,m) if (a[dep][i].k) {
data c=a[dep][i];
int x=find(c.x),y=find(c.y);
a[dep][++nm]=(data){np[x],np[y],c.id,c.k,0};
}
int mid=(l+r)/2;
cdq(dep+1,l,mid,nn,nm);
cdq(dep+1,mid+1,r,nn,nm);
}
int main(){
n=read(); m=read();
int x,y;
rep(i,1,m){
x=read(); y=read();
a[0][i]=(data){x,y,i,0,0};
}
Q=read();
rep(i,1,Q){
b[i][0]=read();
rep(j,1,b[i][0]) b[i][j]=read();
}
cdq(1,1,Q,n,m);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: