Graph
输入文件:graph.in
输出文件:graph.out
时间限制:1 second
空间限制:512 MB
题目描述
现在你要维护一张无向的简单图。你要执行如下操作:
0:加入一条边。保证它不存在。
1:删除一条边。保证它存在。
2:查询两个点是否联通。
输入格式
输入的第一行是两个正整数n,m 。
接下来 行,每一行三个整数opt,x,y 。其中opt 表示操作编号。
输出格式
对于每一个opt = 2的询问,输出一行 Yes 或 No ,表示两个节点是否连通。
样例
样例输入
样例输出
4 10
0 1 2
0 2 3
0 3 1
2 1 4
0 4 3
2 1 4
1 2 3
2 1 4
1 1 3
2 1 4
样例输出
No
Yes
Yes
No
n <= 5000,m <= 2000000
这道题可以lct板子,可以过、、、但是比时间分治劣。(第二次写,然而第一次用lct...然后就忘了,,,,结果只打了个暴力-。-、)
一条边可以存活的时间为x,u;
那么以时间为下标建线段树。
把区间(x,u)加1;
只有线段树上一个结点所代表的区间被(x,u)全部包含才能把这条边加到这个结点上。
dfs每到一个结点把这个结点存的边添加(用栈来记录加了哪些边,用并查集处理,但注意不压缩路径,因为只改一个点的fa,如果压缩了改很多个点的fa.加一条边,改变一个点的所在集合大小,以及另一个点的fa...)
一直到叶子结点如果这个结点所代表的区间(即这个时间点有询问则处理)
如果没有就一直退栈,每到一个点把这个点所存的边,全部删除=、=(即把一个集合的大小改为原来的大小,把另一个点的fa改为原来的fa)
#include<bits/stdc++.h>
using namespace std;
int n, m, vis[2000005],bian[5005][5005], cnt, cx, ha[2000005],ans[2000005], c[2000005], shi[2000005], fa[5005], size[5005], huan[2000005], hui[2000005], cha[2000005], cha1[2000005];
vector<int>bi[2000005];
void read(int &x)
{
x = 0;
char c = getchar();
while(c < '0' || c > '9')
{
c = getchar();
}
while(c >= '0' &&c <= '9')
{
x = 10 * x + c - '0';
c = getchar();
}
}
struct node
{
int fa, x, y;
};
node zhan[2000000];
int find(int x)
{
if(x == fa[x]) return x;
return find(fa[x]);
}
void modify(int o, int l, int r, int ql, int qr, int val)
{
if(ql <= l && r <= qr)
{
bi[o].push_back(val);
return ;
}
int mid = (l + r) >> 1;
if(ql <= mid) modify(2*o, l, mid, ql, qr, val);
if(mid < qr) modify(2*o+1, mid+1, r, ql, qr,val);
}
void dfs(int o, int l, int r, int tp)
{
int he = tp;
int mx = bi[o].size();
for(int i = 0; i < mx; i++)
{
int haha = bi[o][i];
int r1 = find(huan[haha]);
int r2 = find(hui[haha]);
if(r1 != r2)
{
if(size[r1] < size[r2])swap(r1,r2);
zhan[++tp].fa = fa[r2];
zhan[tp].x = r1;
zhan[tp].y = r2;
size[r1] += size[r2];
fa[r2] = r1;
}
}
if(l == r)
{
if(c[l] != 0)
{
int r1 = find(cha[c[l]]);
int r2 = find(cha1[c[l]]);
if(r1 == r2)
{
ans[c[l]] = 1;
}
else ans[c[l]] = 0;
}
for(int i = he +1; i <= tp; i++)
{
int x = zhan[i].x;
int y = zhan[i].y;
size[x] -= size[y];
fa[y] = zhan[i].fa;
}
tp = he;
return ;
}
int mid = (l + r) /2;
dfs(o*2, l, mid, tp );
dfs(o*2+1, mid+1, r, tp );
for(int i = he+1; i <= tp; i++)
{
int x = zhan[i].x;
int y = zhan[i].y;
size[x] -= size[y];
fa[y] = zhan[i].fa;
}
tp = he;
}
int main()
{
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
read(n);
read(m);
for(int i = 1; i <= m; i++)
{
int a,b,d;
read(a);
read(b);
read(d);
if(a == 0)
{
++cnt;
bian[b][d] = bian[d][b] = i;
ha[i] = cnt;
huan[cnt] = b;
hui[cnt] = d;
shi[cnt] = i;
}
if(a == 1)
{
vis[ha[bian[b][d]]]= 1;
modify(1, 1, m, bian[b][d], i, ha[bian[b][d]]);
}
if(a == 2)
{
c[i] = ++cx;
cha[cx] = b;
cha1[cx] = d;
}
}
for(int i = 1; i <= cnt; i++)
if(vis[i] == 0) modify(1, 1, m, shi[i], m,i);
for(int i = 1; i <= n; i++)
{
fa[i] = i; size[i] = 1;
}
dfs(1,1,m,0);
for(int i = 1; i <= cx; i++)
if(ans[i] == 1) printf( "Yes\n" );
else printf("No\n");
return 0;
}