题目链接: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

最新文章

  1. Swift3.0语言教程分割字符串与截取字符串
  2. C++产生随机数四则运算
  3. 根据Url 获取图片尺寸 iOS
  4. GCD使用dispatch_semaphore_t创建多线程网络同步请求
  5. Delphi的&quot;Invalid pointer operation&quot;异常的解决办法
  6. Flex +WebService
  7. 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
  8. 遍历id,根据id作为条件循环查询。
  9. 新手对css的浅识
  10. mbed OS - ARM关于物联网(IoT)的战略布局
  11. Android Service学习之IntentService 深入分析
  12. 如何用webbrowser获取ajax动态生成的网页的源码?
  13. windows c++程序移植到linux的要点
  14. 复习HTML+CSS(2)
  15. Go学习之初出茅庐
  16. SpringSecurityOAuth使用JWT Token实现SSO单点登录
  17. oracle 11g 空表导出
  18. MySQL入门详解(三)---mysql如何进行主从配置
  19. html禁止选中文字
  20. BZOJ1457 棋盘游戏

热门文章

  1. Storm工作流程 vs. Spark Stream
  2. POJ 1265
  3. BZOJ 1044 HAOI2008 木棍切割 二分答案+动态规划
  4. POJ 3280 Cheapest Palindrome DP题解
  5. TensorRT加速 ——NVIDIA终端AI芯片加速用,可以直接利用caffe或TensorFlow生成的模型来predict(inference)
  6. 部署微信定位精灵APK到Genymotion
  7. md5 c# unicode 互换(原创)
  8. [源码管理] ubuntu中svn简明用法:服务器搭建+客户端使用
  9. FluentScheduler定时器
  10. guice基本使用,guice整合guice-servlet,web开发(五)