题目链接:https://cn.vjudge.net/problem/Gym-101615D

题意

给一棵树,每个边权表示一种颜色。

现定义一条彩虹路是每个颜色不相邻的路。

一个好点是所有从该节点开始的所有简单路径(最短路)都是彩虹路。

问有哪几个好点?按编号输出。

思路

按节点遍历,若有多条路边权一样,则这几个子树都不是好点。

除去不好点,剩下即为好点。

一开始的思路是树上dp,然而情况实在太多,WA好几次。

最后看题解,发现有个dfs序的操作,把子树表示成数组里的一个范围,每次区间打标志即可(差分数组)。

提交过程

WA×n 树形dp
AC

代码

#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=5e4+20, maxm=maxn*2;
struct Edge{
int to, nxt, val;
Edge(int to=0, int nxt=0, int val=0):
to(to), nxt(nxt), val(val) {}
}edges[maxm];
int head[maxn], esize;
int tim, st[maxn], siz[maxn], fa[maxn], dfn[maxn];
int n;
void init(void){
memset(head, -1, sizeof(head));
esize=0, tim=0;
} void addEdge(int from, int to, int val){
edges[esize]=Edge(to, head[from], val);
head[from]=esize++;
} void dfs(int u, int pre){
dfn[tim]=u;
st[u]=tim++; siz[u]=1; fa[u]=pre;
#define TO edges[i].to
for (int i=head[u]; i!=-1; i=edges[i].nxt)
if (TO!=pre) dfs(TO, u), siz[u]+=siz[TO];
#undef TO
} int main(void){
int a, b, val;
while (scanf("%d", &n)==1){
init();
for (int i=0; i<n-1; i++){
scanf("%d%d%d", &a, &b, &val);
addEdge(a, b, val);
addEdge(b, a, val);
} dfs(1, -1);
int diff[maxn]={0};
for (int u=1; u<=n; u++){
vector<pair<int, int> > e;
for (int i=head[u]; i!=-1; i=edges[i].nxt)
e.push_back(make_pair(edges[i].val, edges[i].to));
sort(e.begin(), e.end()); int ptr=0, sizes=e.size();
while (ptr<sizes){
int pre=e[ptr].first, tmp=ptr+1;
while (tmp<sizes && pre==e[tmp].first) tmp++;
if (tmp-1==ptr) {ptr++; continue;}
if (pre!=e[tmp-1].first) break; for (; ptr<=tmp-1; ptr++){
int to=e[ptr].second;
// printf("%d: %d st%d siz%d\n", u, to, st[to], siz[to]);
if (to==fa[u]){
diff[st[1]]++;
diff[st[u]]--;
diff[st[u]+siz[u]]++;
}else{
diff[st[to]]++;
diff[st[to]+siz[to]]--;
}
}
}
} for (int i=1; i<=n; i++)
diff[i]+=diff[i-1]; int ans[maxn], asize=0;
for (int i=1; i<=n; i++)
if (diff[st[i]]==0) ans[asize++]=i;
// for (int i=1; i<=n; i++)
// printf("%d: %d siz%d\n", i, st[i], siz[i]);
printf("%d\n", asize);
for (int i=0; i<asize; i++)
printf("%d\n", ans[i]);
} return 0;
}
Time Memory Length Lang Submitted
62ms 4876kB 2466 GNU G++ 5.1.0 2018-08-30 20:57:26

Gym-101615D Rainbow Roads 树的DFS序 差分数组的更多相关文章

  1. [2]树的DFS序

    定义: 树的DFS序就是在对树进行DFS的时候,对树的节点进行重新编号:DFS序有一个很强的性质: 一颗子树的所有节点在DFS序内是连续的一段, 利用这个性质我们可以解决很多问题. 代码: void ...

  2. 树的dfs序 && 系统栈 && c++ rope

    利用树的dfs序解决问题: 就是dfs的时候记录每个节点的进入时间和离开时间,这样一个完整的区间就是一颗完整的树,就转化成了区间维护的问题. 比如hdu3887 本质上是一个求子树和的问题 #incl ...

  3. CF877E Danil and a Part-time Job 线段树维护dfs序

    \(\color{#0066ff}{题目描述}\) 有一棵 n 个点的树,根结点为 1 号点,每个点的权值都是 1 或 0 共有 m 次操作,操作分为两种 get 询问一个点 x 的子树里有多少个 1 ...

  4. HDU4117 GRE WORDS(AC自动机+线段树维护fail树的dfs序)

    Recently George is preparing for the Graduate Record Examinations (GRE for short). Obviously the mos ...

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

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

  6. bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)

    Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...

  7. 2018.11.01 NOIP训练 图论(线段树+倍增+dfs序)

    传送门 一道挺妙的题. 对于询问点(u,v),如右图所示,我们可以发现存在一个点m在u->v的路径中,m子树的点到u是最近的,m子树外到v是最近的.其中dis(u,m)=(dis(u,v)-1) ...

  8. 线段树(dfs序建树加区间更新和单点查询)

    题目链接:https://cn.vjudge.net/contest/66989#problem/J 记录一下这道折磨了我一天的题,.... 具体思路: 具体关系可通过dfs序建树,但是注意,在更新以 ...

  9. bzoj3306: 树(dfs序+倍增+线段树)

    比较傻逼的一道题... 显然求子树最小值就是求出dfs序用线段树维护嘛 换根的时候树的形态不会改变,所以我们可以根据相对于根的位置分类讨论. 如果询问的x是根就直接输出整棵树的最小值. 如果询问的x是 ...

随机推荐

  1. 大数据学习[16]--使用scroll实现Elasticsearch数据遍历和深度分页[转]

    题目:使用scroll实现Elasticsearch数据遍历和深度分页 作者:星爷 出处: http://lxWei.github.io/posts/%E4%BD%BF%E7%94%A8scroll% ...

  2. 0227浅谈MySQL之 Handler_read_*参数

    转自博客http://www.path8.net/tn/archives/5613 1.监控语法: 在MySQL里,使用SHOW STATUS查询服务器状态,语法一般来说如下: SHOW [GLOBA ...

  3. 【ACM】hdu_2020_绝对值排序_201308050929

    绝对值排序 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  4. Eclipse没有Run On Server的问题解决

    1.[项目]->[右击]->[Properties]->[Project Facets]->[Modify Project],选择[Java]和[Dynamic Web Mod ...

  5. Project Euler18题 从上往下邻接和

    题目:By starting at the top of the triangle below and moving to adjacent numbers on the row below, the ...

  6. BZOJ 1044 HAOI2008 木棍切割 二分答案+动态规划

    题目大意:给定n个连在一起的木棍.分成m+1段.使每段最大值最小,求最大值的最小值及最大值最小时切割的方案数 第一问水爆了--二分答案妥妥秒过 第二问就有些难度了 首先我们令f[i][j]表示用前j个 ...

  7. javascript学习笔记(一)-廖雪峰教程

    一. 基础 1.for in,for of和forEach 遍历的是对象的属性,因为数组也是对象,其内部的元素的索引就是其属性值.用该方式遍历数组就是获取了数组中的每一个元素的索引值(从0開始). 而 ...

  8. Android 源代码解析 之 setContentView

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41894125,本文出自:[张鸿洋的博客] 大家在平时的开发中.对于setCont ...

  9. Linux下的五种I/O模型

    堵塞I/O(blocking I/O) 非堵塞I/O (nonblocking I/O) I/O复用(select 和poll) (I/O multiplexing) 信号驱动I/O (signal ...

  10. bzoj3673: 可持久化并查集 by zky&&3674: 可持久化并查集加强版

    主席树可持久化数组,还挺好YY的 然而加强版要路径压缩.. 发现压了都RE 结果看了看数据,默默的把让fx的父亲变成fy反过来让fy的父亲变成fx 搞笑啊 #include<cstdio> ...