题目

题目大意

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

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

没有黑点或至多一个白点


思考历程

这题一看就知道是一个树形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. HTML5 Shiv--解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法

    HTML5的语义化标签以及属性,可以让开发者非常方便地实现清晰的web页面布局.大多数浏览器基本兼容html5,但目前来说ie6/ie7/ie8还不兼容html5标签,所以需要javascript处理 ...

  2. (数据科学学习手札60)用Python实现WGS84、火星坐标系、百度坐标系、web墨卡托四种坐标相互转换

    一.简介 主流被使用的地理坐标系并不统一,常用的有WGS84.GCJ02(火星坐标系).BD09(百度坐标系)以及百度地图中保存矢量信息的web墨卡托,本文利用Python编写相关类以实现4种坐标系统 ...

  3. UVA11427 Expect the Expected 概率dp+全概率公式

    题目传送门 题意:小明每晚都玩游戏,每一盘赢的概率都是p,如果第一盘就赢了,那么就去睡觉,第二天继续玩:否则继续玩,玩到赢的比例大于p才去睡:如果一直玩了n盘还没完成,就再也不玩了:问他玩游戏天数的期 ...

  4. awk 一 文本处理工具

    简介 awk 是逐行扫描文件(从第1行到最后一行),寻找含有目标文本的行: 如果匹配成功,则会在该行上执行用户想要的操作. 反之,则不对行做任何处理. awk 命令的基本格式为: awk [选项] ' ...

  5. js实现canvas保存图片为png格式并下载到本地

    canvas 保存图片 下载到本地 function base64Img2Blob(code){ var parts = code.split(';base64,'); var contentType ...

  6. 关于windows下远程连接Linux服务器的方法(CentOs)

    1.服务器端安装VNC 1) 安装vncserver yum install -y tigervnc-server 2) 修改配置 vi /etc/sysconfig/vncservers   最后两 ...

  7. BZOJ 1697: [Usaco2007 Feb]Cow Sorting牛排序(置换+贪心)

    题面 Description 农夫JOHN准备把他的 N(1 <= N <= 10,000)头牛排队以便于行动.因为脾气大的牛有可能会捣乱,JOHN想把牛按脾气的大小排序.每一头牛的脾气都 ...

  8. NX二次开发-UFUN查询体的类型为实体还是片体UF_MODL_ask_body_type

    NX9+VS2012 #include <uf.h> #include <uf_obj.h> #include <uf_modl.h> #include <u ...

  9. DLL注入技术之劫持进程创建注入

    劫持进程创建注入原理是利用Windows系统中CreateProcess()这个API创建一个进程,并将第6个参数设为CREATE_SUSPENDED,进而创建一个挂起状态的进程,利用这个进程状态进行 ...

  10. LeetCode 176. Second Highest Salary (第二高的薪水)

    题目标签: 题目给了我们一个工资表,让我们返回第二高的工资. 利用Max,把第一高的工资找到,然后利用 NOT IN,去找到第二高的工资. Java Solution: Runtime:  153ms ...