zoukankan      html  css  js  c++  java
  • hdu_5354_Bipartite Graph(cdq分治+并查集判二分图)

    题目链接:hdu_5354_Bipartite Graph

    题意:

    给你一个由无向边连接的图,问对于每一个点来说,如果删除这个点,剩下的点能不能构成一个二分图。

    题解:

    如果每次排除一个点然后去DFS判是否为二分图,那肯定会超时。

    我们可以知道,删除其中一个点,对其他好多的边都不会有影响,所以我们可以将其他点的边先加进去,然后来判断一个区间的点是否可行。

    这就和cdq分治的思想差不多。我们令cdq(l,r)表示解决l到r区间的答案。然后通过并查集来判断已经加入的点是否为二分图。

    并查集在判二分图的时候不能路径压缩,因为我们在cdq过程中会还原并查集的结构。

    这里要注意,如果在更新[l,mid]时候,[mid+1,r]只要不能构成二分图,那么[l,mid]的答案就全部都是0,然后就是在并查集合并的时候要以节点多的树为跟,这样才不会T。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;i++)
     3 using namespace std;
     4 
     5 const int N=1e5+7;
     6 int t,n,m,ed,g[N],v[N*2],nxt[N*2],rk[N],col[N],top,fa[N];
     7 char ans[N];
     8 struct node
     9 {
    10     int u,v,colu,colv,fau,fav,rku,rkv;
    11     node(){}
    12     node(int _u,int _v,int _colu,int _colv,int _fau,int _fav,int _rku,int _rkv):
    13         u(_u),v(_v),colu(_colu),colv(_colv),fau(_fau),fav(_fav),rku(_rku),rkv(_rkv){}
    14 }S[N],tmp;
    15 
    16 void init(){ed=top=0,ans[n+1]=0;F(i,1,n)g[i]=0,rk[i]=col[i]=1,fa[i]=i;}
    17 void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
    18 
    19 inline int find_fa(int x){return fa[x]==x?x:find_fa(fa[x]);}
    20 inline int find_col(int x)
    21 {
    22     if(fa[x]==x)return col[x];
    23     return col[x]?find_col(fa[x]):!find_col(fa[x]);
    24 }
    25 
    26 int merge(int u,int v)
    27 {
    28     int fa_u=find_fa(u),fa_v=find_fa(v);
    29     int col_u=find_col(u),col_v=find_col(v);
    30     if(fa_u==fa_v)
    31     {//如果同根并且同色,又有这条边,该图肯定不是二分图
    32         if(col_u==col_v)return 0;
    33         return 1;
    34     }
    35     int rt,son;
    36     if(rk[fa_u]<rk[fa_v])rt=fa_v,son=fa_u;else rt=fa_u,son=fa_v;//以大树为根
    37     S[++top]=node(rt,son,col[rt],col[son],fa[rt],fa[son],rk[rt],rk[son]);
    38     if(col_u==col_v)col[son]^=1;//如果要合并的两个点的颜色相同,那么将要作为儿子的点改变颜色
    39     fa[son]=rt,rk[rt]+=rk[son];
    40     return 1;
    41 }
    42 
    43 void back(int pre)//还原并查集
    44 {
    45     while(top>pre)
    46     {
    47         tmp=S[top--];
    48         int u=tmp.u,v=tmp.v;
    49         col[u]=tmp.colu,col[v]=tmp.colv;
    50         fa[u]=tmp.fau,fa[v]=tmp.fav;
    51         rk[u]=tmp.rku,rk[v]=tmp.rkv;
    52     }
    53 }
    54 
    55 int unite(int l,int r,int a,int b)
    56 {
    57     F(j,l,r)for(int i=g[j];i;i=nxt[i])
    58     {
    59         if(a<=v[i]&&v[i]<=b)continue;//只合并[l,r]区间的点
    60         if(!merge(j,v[i]))return 0;
    61     }
    62     return 1;
    63 }
    64 
    65 void cdq(int l=1,int r=n,int flag=1)
    66 {
    67     if(l==r){ans[l]=flag+'0';return;}
    68     int mid=l+r>>1,pre=top,now=flag&&unite(mid+1,r,l,mid);
    69     cdq(l,mid,now),back(pre);
    70     now=flag&&unite(l,mid,mid+1,r);
    71     cdq(mid+1,r,now),back(pre);
    72 }
    73 
    74 int main()
    75 {
    76     scanf("%d",&t);
    77     while(t--)
    78     {
    79         scanf("%d%d",&n,&m);
    80         init();
    81         F(i,1,m)
    82         {
    83             int x,y;
    84             scanf("%d%d",&x,&y);
    85             adg(x,y),adg(y,x);
    86         }
    87         cdq(),printf("%s
    ",ans+1);
    88     }
    89     return 0;
    90 }
    View Code
  • 相关阅读:
    mysql 无法连接提示 Authentication plugin &#39;caching_sha2_password&#39; cannot be loaded
    探究分析:快速对大量的数据转换为数组
    SQL Server like 字段
    InfluxDB从原理到实战
    Python学习日记(四十) Mysql数据库篇 八
    MySQL数据库基本操作
    ES入门宝典(详细截图版)
    NameNode &amp;&amp; Secondary NameNode工作机制
    MySQL 两张表关联更新(用一个表的数据更新另一个表的数据)
    mysql单个表拆分成多个表
  • 原文地址:https://www.cnblogs.com/bin-gege/p/6085038.html
Copyright © 2011-2022 走看看