HDU 5354 Bipartite Graph[cdq+并查集]

这道题和2015年北大校赛第三题几乎一模一样。处理方法也是cdq+可删除并查集。
然后判断是不是二分图的方法,就是用并查集判断是否是二分图,看看我们要merge的两个点的各自与父亲相对的颜色。并查集的基本使用方法。
至于cdq和可删除并查集见链接。
当然不一定要像YYN将所有的以前信息都记录在stack中,也可以只记录两个点,然后再存几个数组表示这个点以前的信息就行。

// whn6325689
// Mr.Phoebe
// http://blog.csdn.net/u013007900
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
#include <functional>
#include <numeric>
#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;

#define eps 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LLINF 1LL<<62
#define speed std::ios::sync_with_stdio(false);

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef complex<ld> point;
typedef pair<int, int> pii;
typedef pair<pii, int> piii;
typedef vector<int> vi;

#define CLR(x,y) memset(x,y,sizeof(x))
#define CPY(x,y) memcpy(x,y,sizeof(x))
#define clr(a,x,size) memset(a,x,sizeof(a[0])*(size))
#define cpy(a,x,size) memcpy(a,x,sizeof(a[0])*(size))

#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define lowbit(x) (x&(-x))
#define MID(x,y) (x+((y-x)>>1))

template<class T>
inline bool read(T &n)
{
    T x = 0, tmp = 1;
    char c = getchar();
    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == EOF) return false;
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
    n = x*tmp;
    return true;
}
template <class T>
inline void write(T n)
{
    if(n < 0)
    {
        putchar('-');
        n = -n;
    }
    int len = 0,data[20];
    while(n)
    {
        data[len++] = n%10;
        n /= 10;
    }
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}
//-----------------------------------

const int MAXN=100010;

int n,m;
int fa[MAXN];

struct Edge
{
    int u,v,next;
}e[MAXN<<1];
struct Node
{
    int u,v,colu,colv,rku,rkv,fau,fav;
    Node(){}
    Node(int u,int v,int colu,int colv,int rku,int rkv,int fau,int fav):u(u),v(v),colu(colu),colv(colv),rku(rku),rkv(rkv),fau(fau),fav(fav){}
}s[MAXN];

int col[MAXN];
int head[MAXN],tot;
int rk[MAXN],top;
int ans[MAXN];

void init(int n)
{
    CLR(head,-1);
    tot=0;top=0;
    for(int i=0;i<n+10;i++)
        fa[i]=i,col[i]=1,rk[i]=1;
}

void addedge(int u,int v)
{
    e[tot].u=u;
    e[tot].v=v;
    e[tot].next=head[u];
    head[u]=tot++;
}

int find_fa(int x)
{
    int o=x;
    while(fa[o]!=o) o=fa[o];
    return o;
}

int find_col(int x)
{
    if(fa[x]==x)    return col[x];
    if(!col[x])        return !find_col(fa[x]);
    return find_col(fa[x]);
}

bool merge(int u,int v)
{
    int a=find_fa(u),b=find_fa(v);
    int x=find_col(u),y=find_col(v);
    int root,next;
    if(a==b)
    {
        if(x==y)    return false;
        return true;
    }
    if(rk[a]>rk[b])
        root=a,next=b;
    else
        root=b,next=a;
    s[top++]=Node(a,b,col[a],col[b],rk[a],rk[b],fa[a],fa[b]);
    if(x==y && col[root]==1)
        col[next]^=1;
    fa[next]=root;
    rk[root]+=rk[next];
    return true;
}

bool unite(int l,int r,int a,int b)
{
    bool flag=true;
    int u,v;
    for(int t=l;t<=r;t++)
        for(int i=head[t];~i;i=e[i].next)
        {
            u=e[i].u;v=e[i].v;
            if(a<=v && v<=b)  continue;
            if(!merge(u,v))
                flag=false;
        }
    return flag;
}

void back(int x)
{
    Node tmp;
    while(top>x)
    {
        --top;
        tmp=s[top];
        int u=tmp.u,v=tmp.v;
        rk[u]=tmp.rku;rk[v]=tmp.rkv;
        fa[u]=tmp.fau;fa[v]=tmp.fav;
        col[u]=tmp.colu;col[v]=tmp.colv;
    }
}

void cdq(int l,int r,bool flag)
{
    if(l==r)
    {
        ans[l]=flag;
        return;
    }
    int mid=MID(l,r);
    int pre=top;
    bool now=flag&&unite(mid+1,r,l,mid);
    cdq(l,mid,now);
    back(pre);
    now=flag&&unite(l,mid,mid+1,r);
    cdq(mid+1,r,now);
    back(pre);

}

int main()
{
    int T;
    read(T);
    while(T--)
    {
        read(n),read(m);
        init(n);
        for(int i=0,u,v;i<m;i++)
        {
            read(u);read(v);
            addedge(u,v);
            addedge(v,u);
        }
        cdq(1,n,true);
        for(int i=1;i<=n;i++)
            write(ans[i]);
        putchar('\n');
    }
    return 0;
}

你可能感兴趣的:(HDU 5354 Bipartite Graph[cdq+并查集])