Codeforces Round #319 (Div. 1)E.Painting Edges(并查集)
来源:互联网 发布:销售数据分析ppt 编辑:程序博客网 时间:2024/05/16 14:49
题意:给出n个点,m条边的一张无向图,给出q个操作,每次给一条边染色,假如染色后相同颜色构成的边仍然是二分图,则输出YES并且执行这次染色,否则输出NO并跳过这次染色
n<=50w,m<=50w,颜色数k<=50,q<=50w
分析:经典的题目。套用分治+并查集可以解决这类带删边的判定图的联通性或者是否是二分图的问题。思路就是给每个修改一个作用域(l,r),按照时间分治solve(L,R),假如(l,r)包含(L,R)则将修改作用于整个区间的询问,假如(l,r)和(L,R)不相交,则将这步修改剔除,否则视情况将这步修改放入左区间或者右区间。另外,还需要实现并查集的回退操作,简单的做法就是将每次的修改存下来,并查集不压缩路径而仅使用按秩合并保证复杂度。这样只需要存被合并的节点,这样回退写起来会很方便。
#include<bits/stdc++.h>using namespace std;const int Maxn=500020,Inf=1e9;typedef pair<int,int>pi;int n,m,k,q;int col[Maxn],nxt[Maxn];int qid[Maxn],qc[Maxn],uu[Maxn],vv[Maxn];int f[Maxn*50],val[Maxn*50],sz[Maxn*50];vector<int>Q[Maxn<<2];int rep[Maxn];bool op;int cal(int c,int u){return (c-1)*n+u-1;}pi find(int x){ int ret=0; while(f[x]!=x)ret^=val[x],x=f[x]; ret^=val[x]; return pi(x,ret);}void done(int id,vector<int>&V){ if(col[id]>k){return;} pi u=find(cal(col[id],uu[id])),v=find(cal(col[id],vv[id])); if(u.first==v.first)return; if(sz[u.first]>sz[v.first])swap(u,v); f[u.first]=v.first; sz[v.first]+=sz[u.first]; val[u.first]^=u.second^v.second; V.push_back(u.first);}void rebuild(vector<int>&V){ while(V.size()) { int u=V.back(); V.pop_back(); sz[f[u]]-=sz[u]; f[u]=u; val[u]=1; }}void solve(int l,int r,int x){ if(l==r) { pi u=find(cal(qc[l],uu[qid[l]])),v=find(cal(qc[l],vv[qid[l]])); rep[l]=u!=v; if(u!=v)col[qid[l]]=qc[l]; return ; } vector<int>V; int mid=(l+r)>>1; for(int i=0;i<Q[x].size();i++) { int t=Q[x][i]; if(t<l) { if(nxt[t]<l)continue; if(nxt[t]<=mid)Q[x<<1].push_back(t); else done(qid[t],V); } else if(t>mid)Q[x<<1|1].push_back(t); else Q[x<<1].push_back(t); } solve(l,mid,x<<1); rebuild(V); for(int i=0;i<Q[x].size();i++) { int t=Q[x][i]; if(t<=mid) { if(nxt[t]>r)done(qid[t],V); else if(nxt[t]>mid)Q[x<<1|1].push_back(t); } } solve(mid+1,r,x<<1|1); rebuild(V);}int main(){ scanf("%d%d%d%d",&n,&m,&k,&q); for(int i=1;i<=m;i++) { scanf("%d%d",uu+i,vv+i); } for(int i=1;i<=q;i++) { Q[1].push_back(i); scanf("%d%d",qid+i,qc+i); } for(int i=0;i<=cal(k,n);i++)f[i]=i,sz[i]=1,val[i]=1; for(int i=1;i<=m;i++)col[i]=Inf; for(int i=q;i>=1;i--)nxt[i]=col[qid[i]],col[qid[i]]=i; for(int i=1;i<=m;i++)col[i]=Inf; solve(1,q,1); for(int i=1;i<=q;i++)puts(rep[i]?"YES":"NO");}
0 0
- Codeforces Round #319 (Div. 1)E.Painting Edges(并查集)
- codeforces #576E Painting Edges 分治+并查集
- Codeforces Round #266 (Div. 2) E codeforces466e(dfs序+并查集)
- Codeforces Round #345 (Div. 2) E. Table Compression(并查集)★ ★
- Codeforces Round #266 (Div. 2)-E. Information Graph(dfs+并查集)
- Codeforces Round #416 (Div. 2) E. Vladik and Entertaining Flags(线段树+并查集)
- Codeforces Round #446(Div.2)Problem E Envy(并查集)
- Codeforces Round #250 (Div. 1) B 并查集
- Codeforces Round 650E Clockwork Bomb(并查集)
- Educational Codeforces Round 31 E. Binary Matrix 并查集
- Codeforces Round #400 (Div. 1 + Div. 2, combined) D. The Door Problem 开关--并查集
- Codeforces Round #254 (Div. 2)(并查集,线段树)
- Codeforces Round #218 (Div. 2)---D. Vessels(并查集)
- Codeforces Round #346 (Div. 2) F bfs+并查集
- Codeforces Round #376 (Div. 2) C 并查集
- Codeforces Round #376 (Div. 2) C dfs+并查集
- Codeforces Round #433 (Div. 2) Planning (贪心+并查集)
- Codeforces #449 Div.1 E: Welcome home, Chtholly(分块+并查集)
- Android开发十八大资源分享
- Android中开启布局边界
- 块存储、文件存储、对象存储
- LeetCode 1.Two Sum
- protobuf 在lua中的使用
- Codeforces Round #319 (Div. 1)E.Painting Edges(并查集)
- 敏捷开发之三——像橄榄球运动一样scrum
- android通知的demo之Notification
- LeetCode 235----Lowest Common Ancestor of a Binary Search
- JAVA collection 仿写 学习
- 微信商城开发实战——互动出版网
- Ogre中四元数与三维向量(Unity3D异曲同工)
- IOS开发之消息推送(APNS)
- opencv各种小程序代码