Codeforces 541 F. Asya And Kittens(并查集+DFS)

2023-10-15 06:10

本文主要是介绍Codeforces 541 F. Asya And Kittens(并查集+DFS),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


题目大意是说,输入 n n n,表示有 n n n个数 1 1 1~ n n n,接下来有 n − 1 n-1 n1对关系,每行输入两个数 a a a b b b,表示将 a a a所在的集合与 b b b所在的集合合并,但是合并有前提条件, a a a所在的集合与 b b b所在的集合必须相邻(数组的第一个和最后一个不算相邻)。求这组序列最开始的排列情况,答案不唯一,输出一组答案即可

做这道题前必须会:并查集DFS

并查集很容易想到,因为涉及到多个集合的相关操作,主要是如何模拟两个集合之间的相对位置

创建一个二维邻接表List<Integer>[] t t [ i ] t[i] t[i]中存放的是以 i i i为根节点,所有与 i i i处于同一集合的元素,因此如果合并 a a a b b b,还需要将 b b b所在集合的根节点 f b fb fb添加到 a a a所在集合的根节点 f a fa fa的邻接表中,然后将 f b fb fb的根节点更新为 f a fa fa。具体操作就是

fa = find(a);
fb = find(b);
t[fa].add(fb);
father[fb] = fa; 

合并完了以后就要进行DFS遍历,将二维邻接表中的元素打印出来即是答案,对于样例来说,合并完以后,二维邻接表的状态如下图左边,集合(没有使用路径压缩)状态如下图右边

DFS遍历的时候进入的节点可以是任意节点的根节点,但是由于 n ≥ 2 n \geq 2 n2,所以最好不要寻找 x ( x > 3 ) x(x>3) x(x>3)的根节点作为起点,因为可能 x x x就根本不存在。我以1节点的根节点作为起点进行遍历,也就是dfs(find(1)),那么对于上面的图来说,输出的答案应就是31425

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Scanner;public class Main {static int[] father;static ArrayList<Integer>[] t;static BufferedWriter print = new BufferedWriter(new OutputStreamWriter(System.out));static int find(int x) {if (father[x] == x)return x;return father[x] = find(father[x]);}static void union(int a, int b) {a = find(a);b = find(b);if (a != b) {t[a].add(b);father[b] = a;}}public static void main(String[] args) throws IOException {Scanner cin = new Scanner(new BufferedInputStream(System.in));int n = cin.nextInt();father = new int[n + 1];t = new ArrayList[n + 1];for (int i = 1; i <= n; i++) {father[i] = i;t[i] = new ArrayList<Integer>();}for (int i = 0; i < n - 1; i++) {int p = cin.nextInt();int q = cin.nextInt();union(p, q);}dfs(find(3));print.flush();}static void dfs(int root) throws IOException {print.write(root + " ");for (int i = 0; i < t[root].size(); i++)dfs(t[root].get(i));}
}

使用了一个输入输出优化,避免TLE

这篇关于Codeforces 541 F. Asya And Kittens(并查集+DFS)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/215847

相关文章

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

poj 1182 并查集 食物链类

题意: 有n只动物,分别编号1....n。所有动物都属于A,B,C中的一种,已知A吃B,B吃C,C吃A。 按顺序给出下面两种共K条信息: 1. x 和 y 属于同一类。 2. x 吃 y 。 然而这些信息可能会出错,有可能有的信息和之前给出的信息矛盾,也有的信息可能给出的 x 和 y 不在n的范围内。 求k条信息中有多少条是不正确的。 解析: 对于每只动物,创建3个元素 i

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

Codeforces 482B 线段树

求是否存在这样的n个数; m次操作,每次操作就是三个数 l ,r,val          a[l] & a[l+1] &......&a[r] = val 就是区间l---r上的与的值为val 。 也就是意味着区间[L , R] 每个数要执行 | val 操作  最后判断  a[l] & a[l+1] &......&a[r] 是否= val import ja

POJ1988带权并查集

M u v 将u所在的堆移动到v所在的堆的上面 C u 求u的下面有多少块 带权并查集 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;i

POJ1703带权并查集

D: u v  u与v在不同的集合 A: u v  查询u与v的关系 1)压缩路径过程        fu->root   0  1  u-fu 0                 0  1   1                 1  0 2)合并过程 fu->fv      u->fu   0 1   v->fv 0            1 0 1            0