NOJ 1044 连通 OR 不连通 (离线并查集 + hash)

连通 OR 不连通

时间限制(普通/Java) :1000 MS/ 3000 MS          运行内存限制 : 65536 KByte

总提交 : 333            测试通过 : 65

题目描述

给定一个无向图,一共n个点,请编写一个程序实现两种操作:

D x y 从原图中删除连接x,y节点的边。

Q x y 询问x,y节点是否连通

输入

第一行两个数n,m(5<=n<=40000,1<=m<=100000)

接下来m行,每行一对整数 x y (x,y<=n),表示x,y之间有边相连。保证没有重复的边。

接下来一行一个整数 q(q<=100000)

以下q行每行一种操作,保证不会有非法删除。

输出

按询问次序输出所有Q操作的回答,连通的回答C,不连通的回答D

样例输入

3 3

1 2

1 3

2 3

5

Q 1 2

D 1 2

Q 1 2

D 3 2

Q 1 2

样例输出

C

C

D

题目链接:http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1044

题目分析:因为删边操作比较麻烦,而且这题的数据量比较大,如果是单纯的判连通,我们可以用普通并查集来做,我们可以把删边操作转化为添边操作,方法很简单,反向操作就可以了,开始先将不用被删的边加入并查集(这里需要用到hash,记录一下所有要被删的边),遇到D x y则将其合并,理由很简单,因为在删除它们之前它们是连通的,例如样例,我们先记录下所有输入数据,然后从Q 1 2开始,因为不需要删除的点已经被我们合并,D 3 2时合并 3 2,很显然在D 3
2上面的状态下它们还是相连的,最后用一个数组存储答案,因为是反向操作的,答案数组的输出也得反着输。

#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
using namespace std;
int const MAX = 100005;
int n, m, fa[MAX];
char ans[MAX];
struct EDGE
{
    int u, v;
    bool d;
}e[MAX], q[MAX];
map<int, bool> hash;

void UF_set()
{
    for(int i = 0; i <= MAX; i++)
        fa[i] = i;
}

int Find(int x)
{
    return x == fa[x] ? x : fa[x] = Find(fa[x]);
}

void Union(int a, int b)
{
    int r1 = Find(a);
    int r2 = Find(b);
    if(r1 != r2)
        fa[r2] = r1;
}

int main()
{
    UF_set();
    scanf("%d %d", &n, &m);
    for(int i = 0; i < m; i++)
    {
        scanf("%d %d", &e[i].u, &e[i].v);
        if(e[i].u > e[i].v)
            swap(e[i].u, e[i].v);
    }
    int qnum;
    char s[2];
    scanf("%d", &qnum);
    for(int i = 0; i < qnum; i++)
    {
        scanf("%s %d %d", s, &q[i].u, &q[i].v);
        if(q[i].u > q[i].v)
            swap(q[i].u, q[i].v);
        if(s[0] == 'D')
        {
            q[i].d = true;
            hash[q[i].u * MAX + q[i].v] = true;
        }
        else
            q[i].d = false;
    }
    for(int i = 0; i < m; i++)
        if(!hash[e[i].u * MAX + e[i].v])
            Union(e[i].u, e[i].v);
    int cnt = 0;
    for(int i = qnum - 1; i >= 0; i--)
    {
        if(q[i].d)
            Union(q[i].u, q[i].v);
        else
        {
            if(Find(q[i].u) == Find(q[i].v))
                ans[cnt++] = 'C';
            else
                ans[cnt++] = 'D';
        }
    }
    for(int i = cnt - 1; i >= 0; i--)
        printf("%c\n", ans[i]);
}
时间: 2024-10-10 05:02:32

NOJ 1044 连通 OR 不连通 (离线并查集 + hash)的相关文章

bzoj 1015 维护连通块个数,离线并查集

水. 1 /************************************************************** 2 Problem: 1015 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:2072 ms 7 Memory:14796 kb 8 ****************************************************************/ 9 10 #include

CSUOJ 1601 War (离线并查集求连通块个数)

1601: War Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 130  Solved: 38 [Submit][Status][Web Board] Description AME decided to destroy CH's country. In CH' country, There are N villages, which are numbered from 1 to N. We say two village A and B ar

ACM学习历程—Hihocoder 1291 Building in Sandbox(dfs &amp;&amp; 离线 &amp;&amp; 并查集)

http://hihocoder.com/problemset/problem/1291 前几天比较忙,这次来补一下微软笔试的最后一题,这题是这次微软笔试的第四题,过的人比较少,我当时在调试B题,没时间看这一题.不过打过之前一场BestCoder的应该都会有点思路,虽然BC那题是二维,这题是三维的,但是思路应该是一样的,没错,就是离线加并查集. 正过来考虑的时候,发现第一个要求相邻块是好处理的,但是第二个要求能否到达(1000, 1000, 1000)这个条件似乎比较难判断,当时BC上的题根据题

HDU-5441 Travel 离线-并查集

Travel Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 4680    Accepted Submission(s): 1532 Problem Description Jack likes to travel around the world, but he doesn't like to wait. Now, he is t

2015 ACM/ICPC Asia Regional Changchun Online HDU - 5441 (离线+并查集)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5441 题意:给你n,m,k,代表n个城市,m条边,k次查询,每次查询输入一个x,然后让你一个城市对(u,v)满足两点之间每一条边都不超过x,问有多少对 思路:首先我想到的是dfs求出每个查询小于等于他的一个连通块,然后num*(num-1)就是答案,但是时间只有一秒,这个复杂度是5*1e8,超时了(亲身体验了) 然后我们想这个是离线的,我们可不可以由小到大来推,这样前面的贡献到后面就依然能用了,但是我们

【杭电OJ3938】【离线+并查集】

http://acm.hdu.edu.cn/showproblem.php?pid=3938 Portal Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1921    Accepted Submission(s): 955 Problem Description ZLGG found a magic theory that the b

题解报告:zoj 3261 Connections in Galaxy War(离线并查集)

Description In order to strengthen the defense ability, many stars in galaxy allied together and built many bidirectional tunnels to exchange messages. However, when the Galaxy War began, some tunnels were destroyed by the monsters from another dimen

HUD 3938 protal [ 离线并查集 ]

传送们:HDU_3938 portal 思路:主要是实现处理数据,不然便超时,所谓离线处理. 还有注意,离线的姿势,用cnt+=uset[ u] *uset[ v],,如果重新处理所有的集合,重新算的话,又会超时. #include<iostream> #include<cstdio> #include<algorithm> #include<map> using namespace std; int n,m,q; int uset[10010]; int

集合问题 离线+并查集 HDU 3938

题目大意:给你n个点,m条边,q个询问,每条边有一个val,每次询问也询问一个val,定义:这样条件的两个点(u,v),使得u->v的的价值就是所有的通路中的的最长的边最短.问满足这样的点对有几个. 思路:我们先将询问和边全部都按照val排序,然后我们知道,并查集是可以用来划分集合的,所以我们就用并查集来维护每一个集合就行了. //看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespac