[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 ...
随机推荐
- 最小生成树--Prim及Kruskal
//prim算法#include<cstdio> #include<cmath> #include<cstring> #include<iostream> ...
- 运行Storm实例
- 使用sqlyog工具同步两个相同结构的数据库之间的数据
compare two database data 因为工作上遇到 同一个项目被部署到不同服务器上,原项目(后统称"源")在运行中,后部署的项目(后统称"目标" ...
- 28. string类中方法练习
1. 自己写trim方法 public class Demo3 { public static void main(String[] args) { System.out.println(myTrim ...
- leetcode-159周赛-5232-替换子串得到平衡字符串*
题目描述: 方法: 另: class Solution: def balancedString(self, s: str) -> int: n, req = len(s), len(s) // ...
- HIVE的高级操作
二.视图 1.Hive 的视图和关系型数据库的视图区别 和关系型数据库一样,Hive 也提供了视图的功能,不过请注意,Hive 的视图和关系型数据库的数据还是有很大的区别: (1)只有逻辑视图,没有物 ...
- Oozie框架介绍
Oozie框架: 1.Oozie英文翻译:驯象人 2.Oozie简介 一个基于工作流引擎的开源框架,由Cloudera公司贡献给Apache,提供对Hadoop Mapreduce.Pig Jobs的 ...
- Linux环境上的图形化界面SVN客户端软件“RabbitVCS”
RabbitVCS基本支持所有的Linux发行版本包括ubuntu.Debian.Fedora.Arch Linux.Gentoo.Mandriva.OpenSUSE.RHEL.CentOS 5等.其 ...
- Linux服务器上监控网络带宽的18个常用命令nload, iftop,iptraf-ng, nethogs, vnstat. nagios,运用Ntop监控网络流量
Linux服务器上监控网络带宽的18个常用命令 本文介绍了一些可以用来监控网络使用情况的Linux命令行工具.这些工具可以监控通过网络接口传输的数据,并测量目前哪些数据所传输的速度.入站流量和出站流量 ...
- web开发者性能优化工具(一)
web开发者性能优化工具 1 数据包嗅探器(在性能优化时,查看页面(包括页面中全部资源)的加载过程) HttpWatch (http://www.httpwatch.com/) 把网络流量用图形的 ...