题目

题目大意

给你一棵树,每个节点有三种黑、白、灰三种颜色。

你要割掉一些边(每条边被割需要付出一定的代价),使得森林的每棵树满足:

没有黑点或至多一个白点


思考历程

这题一看就知道是一个树形DP……

对于每棵子树,有\(5\)种状态:

  1. 状态\(00\),表示没有黑点和白点。
  2. 状态\(01\),表示没有黑点,只有一个白点。
  3. 状态\(02\),表示没有黑点,有两个或以上个白点。
  4. 状态\(10\),表示有一个黑点,没有白点。
  5. 状态\(11\),表示有一个黑点,一个白点。

然后就是长长的状态转移方程……

打出来之后交上去,10分……

调到自闭,这才发现,原来状态\(02\)只存了两个白点……


正解

我的做法也是正解之一。

题解的做法比较强大,只有三个状态:

  1. \(F(v)\)表示没有黑点,有任意多白点
  2. \(G(v)\)表示有任意多黑点,没有白点
  3. \(H(v)\)表示有任意多黑点,有一个白点

然后转移即可……


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 300010
int n;
int col[N];
struct EDGE{
int to,w;
EDGE *las;
} e[N*2];
int ne;
EDGE *last[N];
inline void link(int u,int v,int w){
e[ne]={v,w,last[u]};
last[u]=e+ne++;
}
struct Status{
long long _00,_01,_02,_10,_11;
} f[N];
long long g[N];
int fa[N];
inline void bfs(){
static int q[N];
int head=1,tail=1;
q[1]=1;
fa[1]=0;
while (head<=tail){
int x=q[head++];
for (EDGE *ei=last[x];ei;ei=ei->las)
if (ei->to!=fa[x]){
fa[ei->to]=x;
q[++tail]=ei->to;
}
}
memset(f,63,sizeof f);
for (int i=tail;i>=1;--i){
int x=q[i];
if (col[x]==0)
f[x]._10=0;
else if (col[x]==1)
f[x]._01=0;
else
f[x]._00=0;
for (EDGE *ei=last[x];ei;ei=ei->las)
if (ei->to!=fa[x]){
int y=ei->to,w=ei->w;
f[x]._11=min({ f[x]._11+min({f[y]._00,f[y]._10,g[y]+w}),
f[x]._10+min(f[y]._01,f[y]._11),
f[x]._01+f[y]._10,
f[x]._00+f[y]._11});
f[x]._10=min( f[x]._10+min({f[y]._00,f[y]._10,g[y]+w}),
f[x]._00+f[y]._10);
f[x]._02=min({ f[x]._02+min({f[y]._00,f[y]._01,f[y]._02,g[y]+w}),
f[x]._01+min(f[y]._01,f[y]._02),
f[x]._00+f[y]._02});
f[x]._01=min( f[x]._01+min(f[y]._00,g[y]+w),
f[x]._00+f[y]._01);
f[x]._00=f[x]._00+min(f[y]._00,g[y]+w);
}
g[x]=min({f[x]._00,f[x]._01,f[x]._02,f[x]._10,f[x]._11});
}
} int main(){
freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while (T--){
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%d",&col[i]);
memset(last,0,sizeof last);
ne=0;
for (int i=1;i<n;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
link(u,v,w),link(v,u,w);
}
bfs();
printf("%lld\n",g[1]);
}
return 0;
}

总结

DP这种东西,最重要的是细心啊……

[JZOJ3347] 【NOI2013模拟】树的难题的更多相关文章

  1. 【NOI2013模拟】坑带的树(仙人球的同构+圆方树乱搞+计数+HASH)

    [NOI2013模拟]坑带的树 题意: 求\(n\)个点,\(m\)条边的同构仙人球个数. \(n\le 1000\) 这是一道怎么看怎么不可做的题. 这种题,肯定是圆方树啦~ 好,那么首先转为广义圆 ...

  2. FineUI模拟树下拉列表

    模拟树的下拉列表 很多时候,我们希望在下拉列表中显示简单树状的层次结构,在菜单设置.机构设置等场景下这个需求尤为突出.也是基于项目需求的考虑,FineUI增加了模拟树的下拉列表的功能,显示效果如下所示 ...

  3. 「NOI2013」树的计数 解题报告

    「NOI2013」树的计数 这什么神题 考虑对bfs重新编号为1,2,3...n,然后重新搞一下dfs序 设dfs序为\(dfn_i\),dfs序第\(i\)位对应的节点为\(pos_i\) 一个暴力 ...

  4. loj#2665. 「NOI2013」树的计数

    目录 题目链接 题解 代码 题目链接 loj#2665. 「NOI2013」树的计数 题解 求树高的期望 对bfs序分层 考虑同时符合dfs和bfs序的树满足什么条件 第一个点要强制分层 对于bfs序 ...

  5. [BJOI2017]树的难题 点分治 线段树

    题面 [BJOI2017]树的难题 题解 考虑点分治. 对于每个点,将所有边按照颜色排序. 那么只需要考虑如何合并2条链. 有2种情况. 合并路径的接口处2条路径颜色不同 合并路径的接口处2条路径颜色 ...

  6. [BJOI2017]树的难题 点分治,线段树合并

    [BJOI2017]树的难题 LG传送门 点分治+线段树合并. 我不会写单调队列,所以就写了好写的线段树. 考虑对于每一个分治中心,把出边按颜色排序,这样就能把颜色相同的子树放在一起处理.用一棵动态开 ...

  7. 【BZOJ3244】【NOI2013】树的计数(神仙题)

    [BZOJ3244][NOI2013]树的计数(神仙题) 题面 BZOJ 这题有点假,\(bzoj\)上如果要交的话请输出\(ans-0.001,ans,ans+0.001\) 题解 数的形态和编号没 ...

  8. UOJ#122【NOI2013】树的计数

    [NOI2013]树的计数 链接:http://uoj.ac/problem/122 按BFS序来,如果$B_i$与$B_{i-1}$必须在同一层,那么贡献为0,必须在不同层那么贡献为1,都可以贡献为 ...

  9. 【JZOJ3347】树的难题

    description analysis 比较麻烦树形\(DP\) 不过这个我还是不算很懂-- 下次要注意思考,不要怕麻烦 code #pragma GCC optimize("O3&quo ...

随机推荐

  1. javascript 学习犯错记录

    看w3c学习js,有时按自己想法来,会出一些莫名奇妙的错误,而这些问题百度到了,但因为学习原因基础不捞,导致看到了答案,却认为这不是答案 1.一个很简单的 一个html,一个js文件 我想在js中的b ...

  2. 第九篇 数据表设计和保存item到json文件

    上节说到Pipeline会拦截item,根据设置的优先级,item会依次经过这些Pipeline,所以可以通过Pipeline来保存文件到json.数据库等等. 下面是自定义json #存储item到 ...

  3. angularJS select下拉框检测改变

    html:(已引入amazeUI) <div style="width:70px;display:inline-block;"> <form class=&quo ...

  4. where I will go

    为什么我选择了java? 作为一个0基础入门的编程小白,大一的时候我接触了C语言,写了我的第一个程序hello world,内心有点小骄傲(我也能编程了),那时候还不知道java是什么,然而实际公司的 ...

  5. 关于springboot错误:“找不到或无法加载主类”的解决办法

    我从网上找的一个Demo,运行的时候报 错误:“找不到或无法加载主类”,百度了一番,都是说在项目目录打开cmd,使用 mvn install.mvn clean complie之类的命令,都成功了,但 ...

  6. on windows in superset sql lab error "module object has no attribute sigalrm"

    改下  utils.py   文件 It works after doing the following change (sorry for the massed up alignment, prob ...

  7. Dart编程变量

    变量是"存储器中的命名空间",用于存储值.换句话说,它作为程序中值的容器.变量名称称为标识符.以下是标识符的命名规则 - 标识符不能是关键字. 标识符可以包含字母和数字. 标识符不 ...

  8. thinkphp 上传安全

    网站的上传功能也是一个非常容易被攻击的入口,所以对上传功能的安全检查是尤其必要的. 大理石平台支架 系统提供的上传类Think\Upload提供了安全方面的支持,包括对文件后缀.文件类型.文件大小以及 ...

  9. thinkphp环境要求

    框架本身没有什么特别模块要求,具体的应用系统运行环境要求视开发所涉及的模块.ThinkPHP底层运行的内存消耗极低,而本身的文件大小也是轻量级的,因此不会出现空间和内存占用的瓶颈. PHP版本要求 P ...

  10. 字符串匹配dp+bitset,滚动数组优化——hdu5745(经典)

    bitset的经典优化,即把可行性01数组的转移代价降低 bitset的适用情况,当内层状态只和外层状态的上一个状态相关,并且内层状态的相关距离是一个固定的数,可用bitset,换言之,能用滚动数组是 ...