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;
}
时间: 2024-08-01 20:32:23

2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集的相关文章

[hdu 5354] Bipartite Graph 分治 并查集

题意 给定一张 $n$ 个点, $m$ 条边的无向图. 问删去每个点后, 原图是不是二分图. $1 \le n, m \le {10} ^ 5$ . 分析 一个图是二分图 $\Leftrightarrow$ 图中不存在奇环. 判定一个图是不是二分图, 可以使用并查集, 多维护一个当前点与父亲的关系的量 bond . 删除每一个点, 我们有两种维度: 区间加法, 区间减法. 这里考虑区间加法, 即考虑分治. 由于要支持撤销, 所以使用按秩合并的并查集. 注意按照大小合并... 按深度合并会 TLE

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5379 题意:一颗n个节点n-1条边的树,现在要给每个节点标号(1~n),要求:(1)每一层的兄弟节点的标号要是连续的(2)每一颗子树的所有节点标号是连续的.问有多少种标号方案. 解法:对于每一层顶多只能存在2个非叶子节点,否则无解:对于每一层有x个叶子节点,y个非叶子节点,那么ans=(ans * x!)%mod,另外如果y!=0,还得ans=2*ans%mod. #include <bits/st

hdu 5288||2015多校联合第一场1001题

http://acm.hdu.edu.cn/showproblem.php?pid=5288 Problem Description OO has got a array A of size n ,defined a function f(l,r) represent the number of i (l<=i<=r) , that there's no j(l<=j<=r,j<>i) satisfy ai mod aj=0,now OO want to know ∑i

HDU 5352 MZL&#39;s City(2015 多校 第5场,最小费用最大流)

  MZL's City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 291    Accepted Submission(s): 94 Problem Description MZL is an active girl who has her own country. Her big country has N cities nu

hdu5289||2015多校联合第一场1002贪心+RMQ

http://acm.hdu.edu.cn/showproblem.php?pid=5289 Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered from 1 to n in this company, and every staff has a ability. Now, Tom is going to assign a special task to

多校第六场 HDU 4927 JAVA大数类

题目大意:给定一个长度为n的序列a,每次生成一个新的序列,长度为n-1,新序列b中bi=ai+1?ai,直到序列长度为1.输出最后的数. 思路:这题实在是太晕了,比赛的时候搞了四个小时,从T到WA,唉--对算组合还是不太了解啊,现在对组合算比较什么了-- import java.io.*; import java.math.*; import java.util.*; public class Main { public static void main(String[] args) { Sca

2014多校第六场 || HDU 4927 Series 1(杨辉三角组合数)

题目链接 题意 : n个数,每操作一次就变成n-1个数,最后变成一个数,输出这个数,操作是指后一个数减前一个数得到的数写下来. 思路 : 找出几个数,算得时候先不要算出来,用式子代替,例如: 1 2 3 4 5 6 (2-1) (3-2) (4-3) (5-4)(6-5) (3-2-2+1)(4-3-3+2)(5-4-4+3)(6-5-5+4) (4-3-3+2-3+2+2-1)(5-4-4+3-4+3+3-2)(6-5-5+4-5+4+4-3) (5-4-4+3-4+3+3-2-4+3+3-2

多校第4场 HDU 4902 Nice boat 线段树

思路:这题比赛的时候宝哥说的思路我觉得对的,就是当是2操作的时候,先把数放到数组里,最后查询输出的时候再统一计算,不过那时敲得烂死了,debug了两天,靠-- 上午写的vector在pushDown的时候又忘了clear了,然后MLE了一早上,尼玛,还以为用的数组太大超了,然后又改成结构体,还是MLE,最后把别人的代码交上去发现没MLE,疯了一中午,最后无聊的时候才发现这个错误,尼玛--发现自己调试怎么变得这么弱了呢-- 还有一个需要注意的问题是1与2操作的处理上比较容易出错,这也是我WA了一下

HDU 3635 延缓更新的并查集

Dragon Balls Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2839    Accepted Submission(s): 1097 Problem Description Five hundred years later, the number of dragon balls will increase unexpecte