3237: [Ahoi2013]连通图
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1155 Solved: 396
[ Submit][ Status][ Discuss]
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
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<=100000 M<=200000 K<=100000
Source
可以用CDQ分治解决,,不过老是wa一遍才想起为什么错。。。。。
定义Solve(l,r)为处理[l,r]的询问。
先标记[l,mid]的边,看[mid+1,r]的边,如果不在[l,mid]就插入,然后Solve(l,mid)
返回的时候先撤销上次的影响,然后标记[mid+1,r],插入[l,mid],Solve(mid+1,r)
返回的时候还是要撤销上次的影响,,这里老是忘记啊= =
维护图的连通性,支持撤销,用安轶合并的并查集
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<stack>
using namespace std;
const int maxn = 1E5 + 10;
const int maxm = 1E5 + 10;
struct E{
int x,y; E(){}
E(int x,int y): x(x),y(y){}
}edgs[2*maxm];
struct data{
int x,y,Ly; data(){}
data(int x,int y,int Ly): x(x),y(y),Ly(Ly){}
};
int n,m,q,cnt,Mark[2*maxm],fa[maxn],L[maxn];
bool pass = 1,Ans[maxn];
vector <int> v[maxm];
int getfa(int x) {return x == fa[x]?x:getfa(fa[x]);}
void Set_Mark(int l,int r)
{
++cnt;
for (int i = l; i <= r; i++)
for (int j = 0; j < v[i].size(); j++)
Mark[v[i][j]] = cnt;
}
data Add(E e)
{
data ret = data(0,0,0);
int fx = getfa(e.x),fy = getfa(e.y);
if (fx == fy) return ret;
if (L[fx] > L[fy]) swap(fx,fy);
ret = data(fx,fy,L[fy]);
fa[fx] = fy; L[fy] = max(L[fy],L[fx] +1);
return ret;
}
void Insert(int l,int r,stack <data> &s)
{
for (int i = l; i <= r; i++)
for (int j = 0; j < v[i].size(); j++)
{
if (Mark[v[i][j]] == cnt) continue;
data ret = Add(edgs[v[i][j]]);
if (ret.x) s.push(ret);
}
}
void Remove(stack <data> &s)
{
while (!s.empty())
{
data k = s.top(); s.pop();
fa[k.x] = k.x; L[k.y] = k.Ly;
}
}
void Solve(int l,int r)
{
if (l == r)
{
for (int i = 0; i < v[l].size(); i++)
{
int fx = getfa(edgs[v[l][i]].x);
int fy = getfa(edgs[v[l][i]].y);
if (fx != fy) return;
}
Ans[l] = 1; return;
}
int mid = (l + r) >> 1; stack <data> s;
Set_Mark(l,mid); Insert(mid + 1,r,s);
Solve(l,mid); Remove(s); Set_Mark(mid + 1,r);
Insert(l,mid,s); Solve(mid + 1,r); Remove(s);
}
int getint()
{
char ch = getchar(); int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint(); m = getint();
for (int i = 1; i <= n; i++) fa[i] = i;
for (int i = 1; i <= m; i++)
{
int x = getint(),y = getint();
edgs[i] = E(x,y); Add(edgs[i]);
}
int F = getfa(1); q = getint();
for (int i = 2; i <= n; i++)
{
int k = getfa(i);
if (k != F) {pass = 0; break;}
}
if (!pass)
{
while (q--) puts("Disconnected");
return 0;
}
for (int i = 1; i <= q; i++)
{
int c = getint();
while (c--)
{
int x = getint();
v[i].push_back(x);
}
}
for (int i = 1; i <= n; i++) fa[i] = i,L[i] = 0;
Set_Mark(1,q);
for (int i = 1; i <= m; i++)
if (Mark[i] != cnt) Add(edgs[i]);
Solve(1,q);
for (int i = 1; i <= q; i++)
if (Ans[i]) puts("Connected");
else puts("Disconnected");
return 0;
}