BNUOJ 51275 道路修建 Large(并查集)

题目链接:点击打开链接

题意:见链接。(中文题)

思路:该题与普通并查集的不同之处在于,需要查询两个点最早联通的时刻。  我们不妨在结点上维护一些信息:假设结点v, 那么维护ans[v]表示v到父亲结点的时间。 然后查询的时候, 考虑到并查集是一个树形结构, 如果两个顶点联通, 两个顶点之间有唯一路径, 路径上边的最大值就是了。

因为要维护这个关系, 所以显然不能路径压缩, 因为那样会破坏结构, 为了使得树不会退化成一条长长的链, 我们可以按秩合并, 可以证明, 这样最大树高logn, 所以单组查询的复杂度是logn。 总的复杂度是mlogn

细节参见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int mod = 1000000000 + 7;
const int INF = 1000000000;
const int maxn = 100005;
int T,n,m,fa[maxn],ra[maxn],ans[maxn],vis[maxn];
void init() {
    for(int i=1;i<=n;i++) {
        fa[i] = i;
        ra[i] = 0;
        ans[i] = 0;
        vis[i] = -1;
    }
}
int _find(int x) { return fa[x] == x ? x : _find(fa[x]); }
bool Union(int u, int v, int t) {
    int x = _find(u), y = _find(v);
    if(x == y) return false;
    if(ra[x] > ra[y]) {
        fa[y] = x;
        ans[y] = t;
    }
    else {
        fa[x] = y;
        ans[x] = t;
        if(ra[x] == ra[y]) ra[y]++;
    }
    return true;
}
int query(int u, int v) {
    int x = _find(u), y = _find(v);
    if(x != y) return 0;
    int p = u, now = 0, res = 0;
    while(true) {
        vis[p] = now;
        if(fa[p] == p) break;
        now = max(now, ans[p]);
        p = fa[p];
    }
    now = 0;
    p = v;
    while(true) {
        if(vis[p] >= 0) { res = max(now, vis[p]); break; }
        if(fa[p] == p) break;
        now = max(now, ans[p]);
        p = fa[p];
    }
    p = u;
    while(true) {
        vis[p] = -1;
        if(fa[p] == p) break;
        p = fa[p];
    }
    return res;
}
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d",&n,&m);
        init();
        int last = 0, cnt = n, id, u, v;
        for(int i=1;i<=m;i++) {
            scanf("%d%d%d",&id,&u,&v);
            u ^= last; v ^= last;
            if(id == 0) {
                if(Union(u, v, i)) --cnt;
                printf("%d\n",last = cnt);
            }
            else {
                printf("%d\n",last = query(u, v));
            }
        }
    }
    return 0;
}
时间: 2024-08-25 17:29:10

BNUOJ 51275 道路修建 Large(并查集)的相关文章

BNU 51275 道路修建 Large 并查集

分析(引入Q神题解  %%%Q) 如果使用可持久化并查集,二分答案判定连通性,复杂度是O(mlog3n),不能在时限内出解.考虑到并查集实际上是一棵树,可以尝试在边上维护一些信息,假设t时刻加了一条边(u,v),若u和v此时未连通,则在root(u)和root(v)之间连一条权值为t的边,表示u所在集合以及v所在集合在t时刻连通,这样对于一组查询(u,v),如果u和v位于同一个连通块内,只需找出并查集中u到v的路径上的权值最大值,很显然这样是不能路径压缩的,但是可以按秩合并保证树高是O(logn

POJ 2513 Colored Sticks(欧拉道路+字典树+并查集)

http://poj.org/problem?id=2513 题意: 给定一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的. 思路: 题目很明显的是欧拉道路的问题. 欧拉道路的关键是: ①图是连通的. ②最多只能有两个奇点.(不能只存在一个奇点) 本来是想用map映射的,但是太多了,比较费时,这里用字典树的话会比较省时,判断图是否连通可以用并查集来完成. 1 #include<iostream> 2 #include<algori

CSP 地铁修建 最小生成树+并查集

地铁修建 试题编号: 201703-4 试题名称: 地铁修建 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 A市有n个交通枢纽,其中1号和n号非常重要,为了加强运输能力,A市决定在1号到n号枢纽间修建一条地铁. 地铁由很多段隧道组成,每段隧道连接两个交通枢纽.经过勘探,有m段隧道作为候选,两个交通枢纽之间最多只有一条候选的隧道,没有隧道两端连接着同一个交通枢纽. 现在有n家隧道施工的公司,每段候选的隧道只能由一个公司施工,每家公司施工需要的天数一致.而每家公司最多只能修

图论(一):DFS,BFS,邻接链表,并查集

本文总结了图的深度优先搜索,图的广度优先搜索,邻接链表和邻接矩阵的实现,并查集的实现. 0),预备知识 基础词汇:有向图,无向图,带权有向图,带权无向图,有向图中<Vi, Vj>:即Vi--->Vj,弧尾--->弧头,无向图中相邻记为(Vi, Vj),顶点有穷集合V+边的有穷集合E. 图的两种实现方式:1,邻接矩阵:edge[n][n]表示有n个结点,数组内容为权值大小或者是否存在边(∞表示无边,权值或1表示有边,0表示结点到结点本身): 2,邻接链表:针对稀疏矩阵较适宜,为图的每

A1. 道路修建 Small(BNUOJ)

A1. 道路修建 Small Time Limit: 1000ms Memory Limit: 131072KB 64-bit integer IO format: %lld      Java class name: Main Submit Status 无向图初始有个点,从到依次标号,但是没有边, 接下来有次操作,从到依次标号,你需要对每种操作输出相应的结果,操作分为两种: 输入格式 操作说明 输出结果 0_u_v 加入一条连接标号为和标号为的点的边. 输出加边后图中连通块的个数. 1_u_

CSP 201703-4 地铁修建【最小生成树+并查集】

问题描述 试题编号: 201703-4 试题名称: 地铁修建 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 A市有n个交通枢纽,其中1号和n号非常重要,为了加强运输能力,A市决定在1号到n号枢纽间修建一条地铁. 地铁由很多段隧道组成,每段隧道连接两个交通枢纽.经过勘探,有m段隧道作为候选,两个交通枢纽之间最多只有一条候选的隧道,没有隧道两端连接着同一个交通枢纽. 现在有n家隧道施工的公司,每段候选的隧道只能由一个公司施工,每家公司施工需要的天数一致.而每家公司最多只能修

UVa 10129 Play On Words【欧拉道路 并查集 】

题意:给出n个单词,问这n个单词能否首尾接龙,即能否构成欧拉道路 按照紫书上的思路:用并查集来做,取每一个单词的第一个字母,和最后一个字母进行并查集的操作 但这道题目是欧拉道路(下面摘自http://blog.csdn.net/hcbbt/article/details/9316301) 关于欧拉道路(from Titanium大神): 判断有向图是否有欧拉路 1.判断有向图的基图(即有向图转化为无向图)连通性,用简单的DFS即可.如果图都不连通,一定不存在欧拉路 2.在条件1的基础上   对于

bzoj 1196: [HNOI2006]公路修建问题 二分+并查集

题目链接 1196: [HNOI2006]公路修建问题 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1576  Solved: 909[Submit][Status][Discuss] Description OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多.然而,由于该岛屿刚刚开发不久,所以那里的交通情况还是很糟糕.所以,OIER Association组织成立了,旨在建立OI island的交通系统. OI isla

BZOJ 1196 [HNOI2006]公路修建问题(二分答案+并查集)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1196 [题目大意] 对于每条可能维修的公路可选择修一级公路或者二级公路,价值不同 要求图连通,且至少有k条一级公路时最大价值公路价值最小. [题解] 二分答案,从一级公路开始处理,利用并查集验证两个条件. [代码] #include <cstdio> #include <algorithm> using namespace std; const int N=20005;