Gym - 101615 D Rainbow Roads dfs序
题目大意:
给出一颗树,每条边都有一个颜色,对一个点来说,如果其他所有点到这个点的简单路径,相连的边颜色都不同,这个点即合法点,统计所有的合法点。
思路:
对于一个节点来说
1、如果这个节点的两个子节点的边颜色一样,那么这两个子节点的子树都要放弃。
2、如果这个节点的子节点和他的父节点的边的颜色一样,那么子节点所在子树放弃,父节点中除了这个节点以外的其他节点都要放弃。
剩下的点就是合法点。
那怎么做到放弃呢?
先dfs处理出每个节点的dfs序,每个dfs序对应的节点标号,每个节点的子树大小(包括本身),对于第一种情况来说,dfs序在 子树节点dfs序 到 子树节点dfs序加上子树大小 这个左闭右开的区间都要放弃,则用一个数组,左边界加一,右边界减一。
对于第二种情况,放弃的子节点和上述一样处理,父节点就要放弃 dfs序从1到父节点dfs序,父节点dfs序+1到最后所有的点,则对应位置加一或者减一,最后vis[ i ]=vis[ i -1 ] + arr[ i ].处理完后,vis还等于0的点,就是合法的dfs序,找到这个dfs序对应的节点就可以了(dfs的时候就记录过了,大佬说这个做法叫差分约束)。
这题五万个点,每个点三个数据,用读入优化居然没有快,,,可能是我的读入优化还不够优秀吧。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string.h>
#include<sstream>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
#define CLR(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long ll;
inline int rd() {
int f = 1; int x = 0; char s = getchar();
while (s<'0' || s>'9') { if (s == '-')f = -1; s = getchar(); }
while (s >= '0'&&s <= '9') { x = x * 10 + s - '0'; s = getchar(); }x *= f;
return x;
}
int n;
struct edge {
int v, color;
edge(){}
edge(int v,int color): v(v),color(color){} };
bool cmp(edge &a, edge &b)
{
return a.color < b.color;
}
const int maxn = 50010;
vector<edge >g[maxn];
int arr[maxn], fa[maxn], son[maxn], dfn[maxn],tot,cnt,vis[maxn],dir[maxn];
void dfs(int u, int pre)
{
fa[u] = pre;
son[u] = 1;
dfn[u] = ++cnt;
dir[cnt] = u;
for (auto it : g[u])
{
if (it.v == pre)continue;
dfs(it.v, u);
son[u] += son[it.v];
}
}
int main() {
cin >> n;
for (int i = 1; i < n; i++)
{
int u, v, color;
u = rd(), v = rd(), color = rd();
//scanf("%d%d%d", &u, &v, &color);
g[u].push_back(edge(v, color));
g[v].push_back(edge(u, color));
}
dfs(1, 0);
for (int i = 1; i <= n; i++)
{
sort(g[i].begin(), g[i].end(), cmp);
int si = g[i].size();
for (int j = 0; j < si - 1; j++)
{
if (g[i][j].color == g[i][j + 1].color)
{ int x = g[i][j].v, y = g[i][j+1].v;
if (fa[x] == i && fa[y] == i)
{ arr[dfn[x]]++;
arr[dfn[x] + son[x]]--;
arr[dfn[y]]++;
arr[dfn[y] + son[y]]--;
}
else if (fa[x] == i && fa[i] == y)
{ arr[dfn[x]]++;
arr[dfn[x] + son[x]]--;
arr[dfn[1]]++;
arr[dfn[i]]--;
arr[dfn[i] + son[i]]++;
}
else if (fa[y] == i && fa[i] == x)
{
swap(x, y);
arr[dfn[x]]++;
arr[dfn[x] + son[x]]--;
arr[dfn[1]]++;
arr[dfn[i]]--;
arr[dfn[i] + son[i]]++;
}
}
}
}
for (int i = 1; i <= n; i++)
{
vis[i] = vis[i - 1] + arr[i];
}
vector<int >ans;
for (int i = 1; i <= n; i++)
{
if (vis[i] == 0)
{
tot++;
ans.push_back(dir[i]);
}
}
printf("%d\n", tot);
sort(ans.begin(), ans.end());
for (auto it : ans)
{
printf("%d\n", it);
}
}
Gym - 101615 D Rainbow Roads dfs序的更多相关文章
- Gym - 101875I I Will Go (dfs序)
题意:N个人要参加一个局,每个人有自己的好朋友,如果他的好朋友来,他才有可能来.N个人的关系不够成环.Q次查询,问若x来了,y是否肯定来. 分析:若点y是x的祖先,则y肯定回来.一次dfs确定每个点覆 ...
- 【枚举】【DFS序】Gym - 101617G - Rainbow Roads
题意:一颗树,每条边有个颜色,一条路径被定义为“彩虹”,当且仅当其上没有长度大于等于2的同色子路径.一个结点被定义为“超级结点”,当且仅当从其发出的所有路径都是“彩虹”. 枚举所有长度为2,且同色的路 ...
- Gym-101615D Rainbow Roads 树的DFS序 差分数组
题目链接:https://cn.vjudge.net/problem/Gym-101615D 题意 给一棵树,每个边权表示一种颜色. 现定义一条彩虹路是每个颜色不相邻的路. 一个好点是所有从该节点开始 ...
- K. Random Numbers(Gym 101466K + 线段树 + dfs序 + 快速幂 + 唯一分解)
题目链接:http://codeforces.com/gym/101466/problem/K 题目: 题意: 给你一棵有n个节点的树,根节点始终为0,有两种操作: 1.RAND:查询以u为根节点的子 ...
- Codeforces Gym 101142 G Gangsters in Central City (lca+dfs序+树状数组+set)
题意: 树的根节点为水源,编号为 1 .给定编号为 2, 3, 4, …, n 的点的父节点.已知只有叶子节点都是房子. 有 q 个操作,每个操作可以是下列两者之一: + v ,表示编号为 v 的房子 ...
- Random Numbers Gym - 101466K dfs序+线段树
Tamref love random numbers, but he hates recurrent relations, Tamref thinks that mainstream random g ...
- Gym 101142G : Gangsters in Central City(DFS序+LCA+set)
题意:现在有一棵树,1号节点是水源,叶子节点是村庄,现在有些怪兽会占领一些村庄(即只占领叶子节点),现在要割去一些边,使得怪兽到不了水源.给出怪兽占领和离开的情况,现在要割每次回答最小的割,使得怪兽不 ...
- cdoj 574 High-level ancients dfs序+线段树
High-level ancients Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/s ...
- BZOJ 3011: [Usaco2012 Dec]Running Away From the Barn( dfs序 + 主席树 )
子树操作, dfs序即可.然后计算<=L就直接在可持久化线段树上查询 -------------------------------------------------------------- ...
随机推荐
- object类型对象 ref参数如何理解?
class Program { static void Main(string[] args) { Student stu = new Student { Name = "老王" ...
- http协议基础教程
引言 HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和 扩展.目前在WWW中使用的是HTTP/ ...
- MySQL在cmd和python下的常用操作
环境配置1:安装mysql,环境变量添加mysql的bin目录 环境配置2:python安装MySQL-Python 请根据自身操作系统下载安装,否则会报c ++ compile 9.0,import ...
- Android studio导入svn工程
Quick Start——> Check outproject from Version——> Subversion——> ‘+’加号 ——> 输入网址 ——> 注意选择 ...
- PL/SQL批处理语句(二)FORALL
PL/SQL批处理语句(二)FORALL 我们知道PL/SQL程序中运行SQL语句是存在开销的,因为SQL语句是要提交给SQL引擎处理,这种在PL/SQL引擎和SQL引擎之间的控制转移叫做上下文却换, ...
- 奇葩问题 eclipse下 maven项目 java Resource报个小红叉,然而里面却没有小红叉
之前没注意,不知是一开始就有还是这两天才有,说下解决方案: 右击项目“Properties”,在弹出的“Properties”的左侧边框,单击“Project Facets”,打开“Project F ...
- linux中的管道命令
很有用的一个命令,用法如下: A | B 是把A命令的输出作为B命令的输入. 比如我想查看一下我在终端输入过的命令,可以这样: history | less
- Luogu 2375 [NOI2014]动物园
字胡串什么的一直不太会,感觉这题…还蛮本质的 考虑暴力求解:num[i]相当于从一直跳nxt,如果nxt[j] * 2 <= i 那么就累加答案 其实这是一个树的结构,也就是说跳到一个结点满足条 ...
- Java并发之FutureTask
FutureTask实现了Runnable和Future接口,是一个可取消的异步任务.利用开始和取消计算的方法.查询计算是否完成的方法和获取计算结果的方法,此类提供了对 Future 的基本实现.仅在 ...
- sequoiadb的c++应用开发1
使用sequoiadb开发c++应用时需要使用BSON对象,本篇主要讲下BSON的操作方面的东西 1:构建一个_id的BSON对象 BSON的c++驱动给我提供了一个宏BSON,使用该对象可以很方便的 ...