HDU 5354 Bipartite Graph 分治,并查集

来源:互联网 发布:微派网络 融资 编辑:程序博客网 时间:2024/06/05 19:07

题目地址: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;}
0 0
原创粉丝点击