2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集

Posted Lsxxxxxxxxxxxxx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集相关的知识,希望对你有一定的参考价值。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5354

题意:求删去每个点后图是否存在奇环(n,m<=1e5)

解法:很经典的套路,和这题一样:http://www.cnblogs.com/spfa/p/7358672.html CDQ套并查集。 这题最开始是看了南神的代码才懂的,http://blog.csdn.net/hdu2014/article/details/47450709    因为要判断每一个点,而且一旦一个点之外的几个点形成了奇环的话这个点一定就是No,所以用分治来解。先判断每一段之外的点是否会成为奇环,如果是的话,这一段就全是No,反之就把这些点放到并查集里并记录,然后分治当前段,直到分治进行到单个点,分治结束后把并查集还原。真是神奇的分治。orz

 

//HDU 5354
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int>pi;
const int maxn = 400020;
vector<pi>E[maxn*2];
int n,m,f[maxn],sz[maxn],val[maxn],ans[maxn];
bool in(int a, int L, int R){
    return a>=L&&a<=R;
}
void solve(int l, int r, int x, vector<pi>&tp);
pi find_set(int x){
    int ret=x;
    int w=0;
    for(;f[ret]!=ret;ret=f[ret]) w^=val[ret];
    w^=val[ret];
    return pi(ret,w);
}
void CDQ(int l, int r, int x){
    if(l == r){
        ans[l]=1;
        return;
    }
    E[x<<1].clear();
    E[x<<1|1].clear();
    vector<pi>tp[2];
    int mid = (l+r)>>1;
    for(int i=0; i<E[x].size(); i++){
        int a=E[x][i].first,b=E[x][i].second;
        if(in(a,l,mid)||in(b,l,mid)) E[x<<1].push_back(E[x][i]);
        else tp[0].push_back(E[x][i]);
        if(in(a,mid+1,r)||in(b,mid+1,r)) E[x<<1|1].push_back(E[x][i]);
        else tp[1].push_back(E[x][i]);
    }
    solve(l,mid,x<<1,tp[0]);
    solve(mid+1,r,x<<1|1,tp[1]);
}
void solve(int l, int r, int x, vector<pi>&tp)
{
    vector<pi>res;
    bool flag=0;
    for(int i=0; i<tp.size(); i++){
        int u=tp[i].first,v=tp[i].second;
        pi fu = find_set(u), fv = find_set(v);
        if(fu.first==fv.first){
            if(!(fu.second^fv.second)){
                flag = 1;
                break;
            }
        }
        else{
            int t1=sz[fu.first]>sz[fv.first]?fu.first:fv.first;
            int t2=fu.first+fv.first-t1;
            int t3=fu.second^fv.second;
            f[t2]=t1;
            sz[t1]+=sz[t2];
            res.push_back(pi(t2,t3));
            val[t2]^=t3;
        }
    }
    if(flag){
        for(int i=l; i<=r; i++) ans[i]=0;
    }
    else CDQ(l,r,x);
    for(int i=res.size()-1; i>=0; i--){
        int u=res[i].first;
        sz[f[u]]-=sz[u];
        val[u]^=res[i].second;
        f[u]=u;
    }
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        E[1].clear();
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++) f[i]=i,sz[i]=1,val[i]=1;
        for(int i=1; i<=m; i++){
            int u,v;
            scanf("%d%d",&u,&v);
            if(u>v) swap(u,v);
            E[1].push_back(pi(u,v));
        }
        CDQ(1,n,1);
        for(int i=1; i<=n; i++) printf("%d",ans[i]);
        printf("\\n");
    }
    return 0;
}

 

以上是关于2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集的主要内容,如果未能解决你的问题,请参考以下文章

2018多校第6场 1013 hdu6373 Pinball

2017多校第6场 HDU 6105 Gameia 博弈

2015多校第7场 HDU 5379 Mahjong tree 构造,DFS

2017多校第6场 HDU 6096 String AC自动机

2017多校第6场 HDU 6097 Mindis 计算几何,圆的反演

2018 HDU多校第三场赛后补题