题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5354
题意:给你n个点m条边,问对于每一个点,删去它之后的图是否是二分图。( 1<=n,m<=105 )
思路:这题的代码是看了南神的博客之后才懂得,代码也参考了他的代码。南神的题解
因为要判断每一个点,而且一旦一个点之外的几个点形成了奇环的话这个点一定就是No,所以用分治来解。先判断每一段之外的点是否会成为奇环,如果是的话,这一段就全是No,反之就把这些点放到并查集里并记录,然后分治当前段,直到分治进行到单个点,分治结束后把并查集还原。
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<cstdlib> #include<vector> using namespace std; #define MS(x,y) memset(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define lowbit(x) (x&(-x)) typedef long long LL; typedef pair<int,int> P; inline void fre1(){freopen("input.txt","r",stdin);/*freopen("output.txt","w",stdout);*/} inline void fre2(){fclose(stdin);/*fclose(stdout);*/} const int MAXN=1e5+5; const double EPS=1e-8; vector<P> vec[MAXN<<2]; int col[MAXN],siz[MAXN],f[MAXN],ans[MAXN]; int n,m; inline bool isin(int a,int l,int r){ return l<=a&&a<=r; } void process(int l,int r,int rt,vector<P> &V); P findfa(int x){ int ret=x,w=0; for(;ret!=f[ret];ret=f[ret]) w^=col[ret]; w^=col[ret]; return MP(ret,w); } void solve(int l,int r,int rt){ if(l==r){ ans[l]=1; return ; } int m=(l+r)>>1; vec[rt<<1].clear(); vec[rt<<1|1].clear(); vector<P> tp[2]; int len=vec[rt].size(); for(int i=0;i<len;++i){ int u=vec[rt][i].first,v=vec[rt][i].second; if(isin(u,l,m)||isin(v,l,m)) vec[rt<<1].push_back(vec[rt][i]); else tp[0].push_back(vec[rt][i]); if(isin(u,m+1,r)||isin(v,m+1,r)) vec[rt<<1|1].push_back(vec[rt][i]); else tp[1].push_back(vec[rt][i]); } process(l,m,rt<<1,tp[0]); process(m+1,r,rt<<1|1,tp[1]); } void process(int l,int r,int rt,vector<P> &V){ P fu,fv; vector<P> ret; int len=V.size(); bool flag=false; for(int i=0;i<len;++i){ int u=V[i].first,v=V[i].second; fu=findfa(u); fv=findfa(v); if(fu.first==fv.first){ if(fu.second==fv.second){ flag=true; break; } } else{ int t1=fu.first,t2=fv.first; if(siz[t1]<siz[t2]) swap(t1,t2); int t3=fu.second^fv.second; f[t2]=t1; siz[t1]+=siz[t2]; col[t2]^=t3; ret.push_back(MP(t2,t3)); } } if(flag){ for(int i=l;i<=r;++i) ans[i]=0; } else solve(l,r,rt); for(int i=ret.size()-1;i>=0;--i){ int u=ret[i].first; siz[f[u]]-=siz[u]; f[u]=u; col[u]^=ret[i].second; } } int main() { int T,u,v; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) col[i]=1,siz[i]=1,f[i]=i; vec[1].clear(); for(int i=0;i<m;++i){ scanf("%d%d",&u,&v); if(u>v) swap(u,v); vec[1].push_back(MP(u,v)); } solve(1,n,1); for(int i=1;i<=n;++i) putchar(ans[i]+'0'); putchar(10); } return 0; }