题目链接: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. 混乱的URL编码-C#-JavaScript

    文章地址 前后端传值的时候,有时候总是遇到乱码不知道怎么解决,这个还是要分析下各个语言的编码格式 JavaScript中编码有三种方法:escape.encodeURI.encodeURICompon ...

  2. C#--Task知识点

    5天玩转C#并行和多线程编程 TASK使用总结 Task是什么,字面意思是任务 表示一个异步操作.它是异步操作的首选方式.Task是FRAMEWORK4中的新特性,封装了以前的Thread,并管理Th ...

  3. [Cypress] Get started with Cypress

    Adding Cypress to a project is a simple npm install away. We won’t need any global dependencies beyo ...

  4. POJ1789&amp;ZOJ2158--Truck History【最小生成树变形】

    链接:http://poj.org/problem?id=1789 题意:卡车公司有悠久的历史,它的每一种卡车都有一个唯一的字符串来表示,长度为7,它的全部卡车(除了第一辆)都是由曾经的卡车派生出来的 ...

  5. 怎样又一次编译linux内核

    linux作为自由软件.在广大爱好者的支持下,内核版本号不断更新. 新的内核修订了就得内核的bug,并添加了很多新的特性.假设用户须要使用这些新的特性或者依据自己的系统量身定做一个更高效或更稳定的内核 ...

  6. Ylmf_Ghost_Win7_SP1_x64_2017_0113.iso虚拟机安装

    新建虚拟机,将iso镜像配置好,然后开启虚拟机 一开始选择PQ8.05: 找到“作业”菜单---“建立” ,新建一个“主分区”然后点击确定 新建主分区作业之后,如果需要新建其他分区继续进行即可,本例只 ...

  7. Android——build.prop 解析【转】

    本文转载自:http://blog.csdn.net/lengyue1084/article/details/77637354 一.概念 在Android设备shell终端可以看到/system目录下 ...

  8. bzoj1833: [ZJOI2010]count 数字计数(数位DP+记忆化搜索)

    1833: [ZJOI2010]count 数字计数 题目:传送门 题解: 今天是躲不开各种恶心DP了??? %爆靖大佬啊!!! 据说是数位DP裸题...emmm学吧学吧 感觉记忆化搜索特别强: 定义 ...

  9. <% %> in html

    $(document).on('click', '.invoiceNumber', function () { var string = <%= StaticHelper.GetCurrentC ...

  10. [NOIP 2017] 奶酪

    [题目链接] http://uoj.ac/problem/332 [算法] 直接搜索即可 注意使用long long [代码] #include<bits/stdc++.h> using ...