[JZOJ3347] 【NOI2013模拟】树的难题
题目
题目大意
给你一棵树,每个节点有三种黑、白、灰三种颜色。
你要割掉一些边(每条边被割需要付出一定的代价),使得森林的每棵树满足:
没有黑点或至多一个白点。
思考历程
这题一看就知道是一个树形DP……
对于每棵子树,有\(5\)种状态:
- 状态\(00\),表示没有黑点和白点。
- 状态\(01\),表示没有黑点,只有一个白点。
- 状态\(02\),表示没有黑点,有两个或以上个白点。
- 状态\(10\),表示有一个黑点,没有白点。
- 状态\(11\),表示有一个黑点,一个白点。
然后就是长长的状态转移方程……
打出来之后交上去,10分……
调到自闭,这才发现,原来状态\(02\)只存了两个白点……
正解
我的做法也是正解之一。
题解的做法比较强大,只有三个状态:
- \(F(v)\)表示没有黑点,有任意多白点
- \(G(v)\)表示有任意多黑点,没有白点
- \(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模拟】树的难题的更多相关文章
- 【NOI2013模拟】坑带的树(仙人球的同构+圆方树乱搞+计数+HASH)
[NOI2013模拟]坑带的树 题意: 求\(n\)个点,\(m\)条边的同构仙人球个数. \(n\le 1000\) 这是一道怎么看怎么不可做的题. 这种题,肯定是圆方树啦~ 好,那么首先转为广义圆 ...
- FineUI模拟树下拉列表
模拟树的下拉列表 很多时候,我们希望在下拉列表中显示简单树状的层次结构,在菜单设置.机构设置等场景下这个需求尤为突出.也是基于项目需求的考虑,FineUI增加了模拟树的下拉列表的功能,显示效果如下所示 ...
- 「NOI2013」树的计数 解题报告
「NOI2013」树的计数 这什么神题 考虑对bfs重新编号为1,2,3...n,然后重新搞一下dfs序 设dfs序为\(dfn_i\),dfs序第\(i\)位对应的节点为\(pos_i\) 一个暴力 ...
- loj#2665. 「NOI2013」树的计数
目录 题目链接 题解 代码 题目链接 loj#2665. 「NOI2013」树的计数 题解 求树高的期望 对bfs序分层 考虑同时符合dfs和bfs序的树满足什么条件 第一个点要强制分层 对于bfs序 ...
- [BJOI2017]树的难题 点分治 线段树
题面 [BJOI2017]树的难题 题解 考虑点分治. 对于每个点,将所有边按照颜色排序. 那么只需要考虑如何合并2条链. 有2种情况. 合并路径的接口处2条路径颜色不同 合并路径的接口处2条路径颜色 ...
- [BJOI2017]树的难题 点分治,线段树合并
[BJOI2017]树的难题 LG传送门 点分治+线段树合并. 我不会写单调队列,所以就写了好写的线段树. 考虑对于每一个分治中心,把出边按颜色排序,这样就能把颜色相同的子树放在一起处理.用一棵动态开 ...
- 【BZOJ3244】【NOI2013】树的计数(神仙题)
[BZOJ3244][NOI2013]树的计数(神仙题) 题面 BZOJ 这题有点假,\(bzoj\)上如果要交的话请输出\(ans-0.001,ans,ans+0.001\) 题解 数的形态和编号没 ...
- UOJ#122【NOI2013】树的计数
[NOI2013]树的计数 链接:http://uoj.ac/problem/122 按BFS序来,如果$B_i$与$B_{i-1}$必须在同一层,那么贡献为0,必须在不同层那么贡献为1,都可以贡献为 ...
- 【JZOJ3347】树的难题
description analysis 比较麻烦树形\(DP\) 不过这个我还是不算很懂-- 下次要注意思考,不要怕麻烦 code #pragma GCC optimize("O3&quo ...
随机推荐
- javascript 学习犯错记录
看w3c学习js,有时按自己想法来,会出一些莫名奇妙的错误,而这些问题百度到了,但因为学习原因基础不捞,导致看到了答案,却认为这不是答案 1.一个很简单的 一个html,一个js文件 我想在js中的b ...
- 第九篇 数据表设计和保存item到json文件
上节说到Pipeline会拦截item,根据设置的优先级,item会依次经过这些Pipeline,所以可以通过Pipeline来保存文件到json.数据库等等. 下面是自定义json #存储item到 ...
- angularJS select下拉框检测改变
html:(已引入amazeUI) <div style="width:70px;display:inline-block;"> <form class=&quo ...
- where I will go
为什么我选择了java? 作为一个0基础入门的编程小白,大一的时候我接触了C语言,写了我的第一个程序hello world,内心有点小骄傲(我也能编程了),那时候还不知道java是什么,然而实际公司的 ...
- 关于springboot错误:“找不到或无法加载主类”的解决办法
我从网上找的一个Demo,运行的时候报 错误:“找不到或无法加载主类”,百度了一番,都是说在项目目录打开cmd,使用 mvn install.mvn clean complie之类的命令,都成功了,但 ...
- 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 ...
- Dart编程变量
变量是"存储器中的命名空间",用于存储值.换句话说,它作为程序中值的容器.变量名称称为标识符.以下是标识符的命名规则 - 标识符不能是关键字. 标识符可以包含字母和数字. 标识符不 ...
- thinkphp 上传安全
网站的上传功能也是一个非常容易被攻击的入口,所以对上传功能的安全检查是尤其必要的. 大理石平台支架 系统提供的上传类Think\Upload提供了安全方面的支持,包括对文件后缀.文件类型.文件大小以及 ...
- thinkphp环境要求
框架本身没有什么特别模块要求,具体的应用系统运行环境要求视开发所涉及的模块.ThinkPHP底层运行的内存消耗极低,而本身的文件大小也是轻量级的,因此不会出现空间和内存占用的瓶颈. PHP版本要求 P ...
- 字符串匹配dp+bitset,滚动数组优化——hdu5745(经典)
bitset的经典优化,即把可行性01数组的转移代价降低 bitset的适用情况,当内层状态只和外层状态的上一个状态相关,并且内层状态的相关距离是一个固定的数,可用bitset,换言之,能用滚动数组是 ...