4025: 二分图
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1726 Solved: 641
[ Submit][ Status][ Discuss]
Description
神犇有一个n个节点的图。因为神犇是神犇,所以在T时间内一些边会出现后消失。神犇要求出每一时间段内这个图是否是二分图。这么简单的问题神犇当然会做了,于是他想考考你。
Input
输入数据的第一行是三个整数n,m,T。
第2行到第m+1行,每行4个整数u,v,start,end。第i+1行的四个整数表示第i条边连接u,v两个点,这条边在start时刻出现,在第end时刻消失。
Output
输出包含T行。在第i行中,如果第i时间段内这个图是二分图,那么输出“Yes”,否则输出“No”,不含引号。
Sample Input
3 3 3
1 2 0 2
2 3 0 3
1 3 1 2
Sample Output
Yes
No
Yes
按时间分治
对于当前分治区间[L, R],查询区间[l, r]
①满足l==L && r==R:
这条边加入图中,出现奇环说明时间[L, R]内一定都不是二分图,剪枝return
②满足r<=(L+R)/2或者l>(L+R)/2:
先不管,扔到两堆里等分治子区间
③满足l<=(L+R)/2 && r>(L+R)/2:
因为这条边横跨分治中线,将这条边从中间拆成两条,等分治子区间
当递归到L==R时还没有return,说明此时一定是二分图
主要是①如何在加完边之后快速判断是不是形成奇环
②当然你还要删边
其实一个并查集就够了
因为要删边,所以压缩路径没有意义也不可以,但可以按秩合并
复杂度O(mlog²n)
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
typedef struct
{
int x, y;
int s, t;
}Road;
Road now, X, Y;
int top, fa[100005], val[100005], root[100005], st[200005];
int Find(int x)
{
while(fa[x]!=x)
x = fa[x];
return fa[x];
}
int Dis(int x)
{
int ans;
ans = 0;
while(fa[x]!=x && fa[x])
ans ^= val[x], x = fa[x];
return ans;
}
void Union(int x, int y, int len)
{
if(x==y)
return;
if(root[x]>root[y])
swap(x, y);
if(root[x]==root[y])
{
root[y]++;
st[++top] = -y;
}
fa[x] = y;
val[x] = len;
st[++top] = x;
}
void Delete(int end)
{
while(end<top)
{
if(st[top]<0)
root[-st[top]]--;
else
{
fa[st[top]] = st[top];
val[st[top]] = 0;
}
top--;
}
}
void CDQ(int l, int r, vector<Road> &E)
{
int m, i, t1, t2, len, end;
vector<Road> L, R;
m = (l+r)/2;
end = top;
for(i=0;i<E.size();i++)
{
now = E[i];
if(now.s==l && now.t==r)
{
t1 = Find(now.x);
t2 = Find(now.y);
len = Dis(now.x)^Dis(now.y)^1;
if(t1!=t2)
Union(t1, t2, len);
else if(len)
{
for(i=l;i<=r;i++)
printf("No\n");
Delete(end);
return;
}
}
else if(now.t<=m)
L.push_back(now);
else if(now.s>=m+1)
R.push_back(now);
else
{
X.s = now.s, X.t = m;
X.x = now.x, X.y = now.y;
L.push_back(X);
Y.s = m+1, Y.t = now.t;
Y.x = now.x, Y.y = now.y;
R.push_back(Y);
}
}
if(l==r)
printf("Yes\n");
else
{
CDQ(l, m, L);
CDQ(m+1, r, R);
}
Delete(end);
}
int main(void)
{
int T, n, m, i;
vector<Road> E;
scanf("%d%d%d", &n, &m, &T);
for(i=1;i<=n;i++)
fa[i] = i;
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d", &now.x, &now.y, &now.s, &now.t);
now.s += 1;
if(now.s>now.t)
continue;
E.push_back(now);
}
CDQ(1, T, E);
return 0;
}
/*
3 3 5
1 2 0 5
2 3 0 5
1 3 0 4
*/