题目传送门

题目大意:

给出一颗树,每条边都有一个颜色,对一个点来说,如果其他所有点到这个点的简单路径,相连的边颜色都不同,这个点即合法点,统计所有的合法点。

思路:

对于一个节点来说

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序的更多相关文章

  1. Gym - 101875I I Will Go (dfs序)

    题意:N个人要参加一个局,每个人有自己的好朋友,如果他的好朋友来,他才有可能来.N个人的关系不够成环.Q次查询,问若x来了,y是否肯定来. 分析:若点y是x的祖先,则y肯定回来.一次dfs确定每个点覆 ...

  2. 【枚举】【DFS序】Gym - 101617G - Rainbow Roads

    题意:一颗树,每条边有个颜色,一条路径被定义为“彩虹”,当且仅当其上没有长度大于等于2的同色子路径.一个结点被定义为“超级结点”,当且仅当从其发出的所有路径都是“彩虹”. 枚举所有长度为2,且同色的路 ...

  3. Gym-101615D Rainbow Roads 树的DFS序 差分数组

    题目链接:https://cn.vjudge.net/problem/Gym-101615D 题意 给一棵树,每个边权表示一种颜色. 现定义一条彩虹路是每个颜色不相邻的路. 一个好点是所有从该节点开始 ...

  4. K. Random Numbers(Gym 101466K + 线段树 + dfs序 + 快速幂 + 唯一分解)

    题目链接:http://codeforces.com/gym/101466/problem/K 题目: 题意: 给你一棵有n个节点的树,根节点始终为0,有两种操作: 1.RAND:查询以u为根节点的子 ...

  5. Codeforces Gym 101142 G Gangsters in Central City (lca+dfs序+树状数组+set)

    题意: 树的根节点为水源,编号为 1 .给定编号为 2, 3, 4, …, n 的点的父节点.已知只有叶子节点都是房子. 有 q 个操作,每个操作可以是下列两者之一: + v ,表示编号为 v 的房子 ...

  6. Random Numbers Gym - 101466K dfs序+线段树

    Tamref love random numbers, but he hates recurrent relations, Tamref thinks that mainstream random g ...

  7. Gym 101142G : Gangsters in Central City(DFS序+LCA+set)

    题意:现在有一棵树,1号节点是水源,叶子节点是村庄,现在有些怪兽会占领一些村庄(即只占领叶子节点),现在要割去一些边,使得怪兽到不了水源.给出怪兽占领和离开的情况,现在要割每次回答最小的割,使得怪兽不 ...

  8. cdoj 574 High-level ancients dfs序+线段树

    High-level ancients Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/s ...

  9. BZOJ 3011: [Usaco2012 Dec]Running Away From the Barn( dfs序 + 主席树 )

    子树操作, dfs序即可.然后计算<=L就直接在可持久化线段树上查询 -------------------------------------------------------------- ...

随机推荐

  1. asp.net的验证码插件及方法、ashx验证码一般处理程序

    需要引入一个ashx的一般处理程序! 把这个程序在前台当作一个图片使用就可以! 前台代码: <td> <img title="看不清?" style=" ...

  2. Xcode快捷

  3. day17 10.jdbc的crud操作

    每次都是注册驱动,获取连接,然后执行.每次都写很累,肯定能抽取出来一些东西.Java里面是这样的,相同的东西可以抽取做成一个方法.用的时候调这方法就OK了.这方法抽取到什么程度呢? package c ...

  4. 列表控件JList的使用

    --------------siwuxie095                             工程名:TestUI 包名:com.siwuxie095.ui 类名:TestList.jav ...

  5. Entity Framework Tutorial Basics(20):Persistence in Entity Framework

    Persistence in Entity Framework There are two scenarios when persisting an entity using EntityFramew ...

  6. jQuery选择器和选取方法.RP

    我们已经使用了带有简单Css选择器的jQuery选取函数:$().现在是时候深入了解jQuery选择器语法,以及一些提取和扩充选中元素集的方法了. 一.jQuery选择器 在CSS3选择器标淮草案定义 ...

  7. 《Maven实战》笔记-8-构建部署Web项目

      一.Web项目结构 1.显式指定Web项目打包方式为war:   2.默认目录 根据“约定大于配置”的规则,Web项目的类及资源文件默认位置为src/main/java和src/main/reso ...

  8. 一劳永逸搭建android开发环境(android官网reference sample api tutorial全下载)

    [摘要]本文简单介绍了android开发环境的搭建,重点介绍了SDK manager和AVD升级问题:并提供了android reference,sample,api,及docs的下载信息. [1]为 ...

  9. iOS symbolicatecrash工具crash日志分析

    若一个App没有加入Crashlytics或者Buggly这些崩溃日志监控,那么我们在App崩溃的时候如何获取崩溃信息呢? 此时我们可以通过symbolicatecrash工具对手机日志来进行分析定位 ...

  10. C#知识点总结系列:3、C#中Delegate和Event

    一.Delegate委托可以理解为一个方法签名. 可以将方法作为另外一个方法的参数带入其中进行运算.在C#中我们有三种方式去创建委托,分别如下: public delegate void Print( ...