题目

题目大意

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

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

没有黑点或至多一个白点


思考历程

这题一看就知道是一个树形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. ps--窗口配置

    移动工具设置 v 选择图层自动选择不勾 图层ctrl + 左键 视图设置智能参考线标尺 Ctrl+r 窗口设置 关闭 库 颜色 打开 信息 字符 图层 历史记录 信息 面板选项 鼠标单位 像素 rgb ...

  2. 自学Oracle心得

    基本术语: global name         全局数据库名 service name        服务名 SID                    实例名 常用命令: 1.       s ...

  3. 三.Python数据类型详述

    Python第三节数据类型详述 一.多变量赋值 python允许多变量赋值 多变量赋相同的值a = b = c = 1 多变量赋不同的值a, b, c = 1, 2, "fuckyou&qu ...

  4. linux redis安装及JAVA使用jedis

    一.redis安装 1.安装redis 将redis安装包放到指定目录下.并用tar -zxvf redis.*****.tar.gz解压2.想把redis安装到哪里,就在哪里创建redis文件夹. ...

  5. 笔记51 Mybatis快速入门(二)

    Mybatis的CRUD 1.修改配置文件Category.xml,提供CRUD对应的sql语句. <?xml version="1.0" encoding="UT ...

  6. Thinkphp 3.2 去掉index.php

    1.httpd.conf中去掉LoadModule rewrite_module modules/mod_rewrite.so 前面的#号 2.httpd.conf 中  AllowOverride ...

  7. delphi xe10 网络连接

    //当前网络状态(引用 Androidapi.JNI.Network.pas) IsConnected //连接 IsWiFiConnected //Wifi是否连接 IsMobileConnecte ...

  8. Python self的用法

    1)不加self是局部变量,只在这个方法里有效:加self则是实例变量,相当于别的函数定义的变量你实例化出来就可以使用 #coding:utf-8 class Person: def __init__ ...

  9. centos6|centos7防火墙区别 | 网络配置区别

    CentOS 6 Linux防火墙 service iptables status (功能描述:查看防火墙状态) chkconfig iptables –list (功能描述:查看防火墙开机启动状态) ...

  10. 牛客多校第九场 D Knapsack Cryptosystem 背包

    题意: 给你32个物品,给定一个容积,让你恰好把这个背包装满,求出装满的方案 题解: 暴力计算的话,复杂度$2^{32}$肯定会炸,考虑一种类似bsgs的算法,先用$2^{16}$的时间遍历前一半物品 ...