洛谷 P4516 潜入行动

2024-03-24 07:32
文章标签 洛谷 行动 潜入 p4516

本文主要是介绍洛谷 P4516 潜入行动,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原题:
外星人又双叒叕要攻打地球了,外星母舰已经向地球航行!这一次,JYY 已经联系好了黄金舰队,打算联合所有 JSOIer 抵御外星人的进攻。

在黄金舰队就位之前,JYY 打算事先了解外星人的进攻计划。现在,携带了监听设备的特工已经秘密潜入了外星人的母舰,准备对外星人的通信实施监听。

外星人的母舰可以看成是一棵 n 个节点、 n−1 条边的无向树,树上的节点用 1,2,⋯ ,n 编号。JYY 的特工已经装备了隐形模块,可以在外星人母舰中不受限制地活动,可以神不知鬼不觉地在节点上安装监听设备。

如果在节点 u上安装监听设备,则 JYY 能够监听与 u直接相邻所有的节点的通信。换言之,如果在节点 u安装监听设备,则对于树中每一条边(u,v) ,节点 v 都会被监听。特别注意放置在节点 u 的监听设备并不监听 u 本身的通信,这是 JYY 特别为了防止外星人察觉部署的战术。

JYY 的特工一共携带了 k 个监听设备,现在 JYY 想知道,有多少种不同的放置监听设备的方法,能够使得母舰上所有节点的通信都被监听?为了避免浪费,每个节点至多只能安装一个监听设备,且监听设备必须被用完。
输入格式

输入第一行包含两个整数 n,k ,表示母舰节点的数量 n 和监听设备的数量 k 。 接下来 n−1行,每行两个整数 u,v(1≤u,v≤n),表示树中的一条边。
输出格式

输出一行,表示满足条件的方案数。因为答案可能很大,你只需要输出答案 mod 1,000,000,007的余数即可。
输入输出样例
输入 #1

5 3
1 2
2 3
3 4
4 5

输出 #1

1

说明/提示

样例 1 解释

样例数据是一条链 1−2−3−4−5。首先,节点 2和 4 必须放置监听设备,否则 1,5将无法被监听(放置的监听设备无法监听它所在的节点)。剩下一个设备必须放置在 3 号节点以同时监听 2,4。因此在 2,3,4节点放置监听设备是唯一合法的方案。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;const int maxn = 1e5 + 1;
const  int mod = 1e9 + 7;
int n, k;
int dp[maxn][101][2][2];
int cnt[maxn];
int tmp[101][2][2];
vector<int> G[maxn];inline int add(ll x, ll y)
{x %= mod;y %= mod;return (int) (x+y) % mod;
}void dfs(int u,int fa){cnt[u] = dp[u][0][0][0]=dp[u][1][1][0]=1;for(int e = 0; e < G[u].size(); e++){int v=G[u][e];if(v==fa) continue;dfs(v,u);for(int i=0;i<=min(cnt[u],k);++i){tmp[i][0][0]=dp[u][i][0][0],dp[u][i][0][0]=0;tmp[i][0][1]=dp[u][i][0][1],dp[u][i][0][1]=0;tmp[i][1][0]=dp[u][i][1][0],dp[u][i][1][0]=0;tmp[i][1][1]=dp[u][i][1][1],dp[u][i][1][1]=0;}for(int i=0;i<=min(cnt[u],k);++i){for(int j=0;j<=min(cnt[v],k-i);++j){dp[u][i+j][0][0]=add((ll)dp[u][i+j][0][0],(ll)tmp[i][0][0]*(ll)dp[v][j][0][1]);dp[u][i+j][0][1]=add((ll)dp[u][i+j][0][1],(ll)tmp[i][0][0]*(ll)dp[v][j][1][1]+(ll)tmp[i][0][1]*((ll)dp[v][j][1][1]+(ll)dp[v][j][0][1]));dp[u][i+j][1][0]=add((ll)dp[u][i+j][1][0],(ll)tmp[i][1][0]*((ll)dp[v][j][0][0]+(ll)dp[v][j][0][1]));dp[u][i+j][1][1]=add((ll)dp[u][i+j][1][1],(ll)tmp[i][1][0]*((ll)dp[v][j][1][0]+(ll)dp[v][j][1][1])+(ll)tmp[i][1][1]*((ll)dp[v][j][0][0]+(ll)dp[v][j][0][1]+(ll)dp[v][j][1][0]+(ll)dp[v][j][1][1]));}}cnt[u]+=cnt[v];}
}int main()
{ios::sync_with_stdio(false);while(cin>>n>>k){int a,b;for (int i=1;i<n;i++){cin>>a>>b;G[a].push_back(b);G[b].push_back(a);}dfs(1, 0);cout << (dp[1][k][0][1] + dp[1][k][1][1]) % mod << endl;}return 0;
}

解答:

这题不会,没想出来 =_=
看洛谷上那群OI的神仙说这是个简单题,感觉很受打击,另外好久没做组合计数的题目了,也很生疏。

下面的解析主要思考为什么要设置题解中的状态。

该题目的难点在于如何设置状态,使得状态转移方程满足树形dp的性质。
假如考虑到已经知道这是一个树形dp的问题,那么子状态肯定是由子树描述。

该问题关键在于如何将子树的状态合并到根上。

假设某节点u,有n个子节点,分别为 v 1 , v 2 . . . v n v_1, v_2... v_n v1,v2...vn
假设dp(u, i)表示以u为根节点的子树放置i个设备能够覆盖节点u以及其子树全部节点的方案数。
考虑状态转移,子节点状态转移的顺序分别是 v 1 , v 2 . . . v n v_1,v_2... v_n v1,v2...vn
考虑vn节点节点的合并,影响u节点是否被覆盖与 v 1 , v 2 . . . v n − 1 v_1, v_2... v_{n-1} v1,v2...vn1这些叶子节点中是否有放置设备的情况有关,如果这n-1个叶子节点一个放置设备的否没有,要保证u节点被覆盖,那么 v n v_n vn节点就必须要放置设备。
但是有个问题,怎样才能知道前n-1个节点到底有没有放置设备呢?

可以考虑增加一个状态,即增加一个当前节点是否被覆盖,用来分开计数。
即设置 d p ( u , i , a ) dp(u,i,a) dp(u,i,a) 表示以u为根节点,安装了i个装置,且是否被覆盖。

那么状态转移可以分成如下几种情况进行合并子树:
如果u节点被覆盖,计数的过程中需要考虑两种情况,一种是 d p ( u , i , 1 ) × d p ( v , i − j , 0 ) + d p ( u , i , 1 ) × d p ( v , i − j , 1 ) dp(u,i,1) × dp(v,i-j,0) + dp(u,i,1) × dp(v,i-j,1) dp(u,i,1)×dp(v,ij,0)+dp(u,i,1)×dp(v,ij,1) 表示如果u节点被覆盖,那么子节点v的状态可以是被覆盖也可以是不被覆盖的。
此外,需要考虑如果u节点不被覆盖时转移到u节点被覆盖的情况,即 d p ( u , i , 0 ) dp(u,i,0) dp(u,i,0)转移到 d p ( u , i , 1 ) dp(u,i,1) dp(u,i,1),此时需要保证当前的叶子节点v必须放置一个设备才能满足计数条件,但是状态里面没有表述,所以仅仅有三个状态还是不满足的,因此需要增加第四个状态,即该点是否放置装置。
d p ( u , i , b , a ) dp(u,i,b,a) dp(u,i,b,a)表示当前u放置了i个设备,该节点是否放置设备以及该节点是否被监听。
那么,状态转移的过程如下:

一下内容来自洛谷讨论区的题解

如果u没被监听,叶子节点v不能放装置,因此
d p [ u ] [ i + j ] [ 0 ] [ 0 ] = ∑ d p [ u ] [ i ] [ 0 ] [ 0 ] ∗ d p [ v ] [ j ] [ 0 ] [ 1 ] d p [ x ] [ i + j ] [ 0 ] [ 0 ] dp[u][i+j][0][0]=∑dp[u][i][0][0]∗dp[v][j][0][1]dp[x][i+j][0][0] dp[u][i+j][0][0]=dp[u][i][0][0]dp[v][j][0][1]dp[x][i+j][0][0]

如果u没被监听但是放了装置,u侧的状态一定是 d p [ u ] [ i ] [ 1 ] [ 0 ] dp[u][i][1][0] dp[u][i][1][0],v是否被监听无所谓但是不能放装置,因此
d p [ u ] [ i + j ] [ 1 ] [ 0 ] = ∑ d p [ u ] [ i ] [ 1 ] [ 0 ] ∗ ( d p [ v ] [ j ] [ 0 ] [ 0 ] + d p [ v ] [ j ] [ 0 ] [ 1 ] ) dp[u][i+j][1][0]=∑dp[u][i][1][0]∗(dp[v][j][0][0]+dp[v][j][0][1]) dp[u][i+j][1][0]=dp[u][i][1][0](dp[v][j][0][0]+dp[v][j][0][1])

如果u没放装置但是被监听了,这时候要分情况:

u侧的状态是 d p [ u ] [ i ] [ 0 ] [ 1 ] dp[u][i][0][1] dp[u][i][0][1],这时候反正u已经被监听了,v放不放装置都无所谓,但是必须保证v是被监听的,所以贡献是 d p [ u ] [ i ] [ 0 ] [ 1 ] ∗ ( d p [ v ] [ j ] [ 0 ] [ 1 ] + d p [ v ] [ j ] [ 1 ] [ 1 ] ) dp[u][i][0][1]∗(dp[v][j][0][1]+dp[v][j][1][1]) dp[u][i][0][1](dp[v][j][0][1]+dp[v][j][1][1])

u侧的状态是 d p [ u ] [ i ] [ 0 ] [ 0 ] dp[u][i][0][0] dp[u][i][0][0],这时候监听u的重任就要交给v了,同时v自己必须是被监听的,所以贡献是
d p [ u ] [ i ] [ 0 ] [ 0 ] ∗ d p [ v ] [ j ] [ 1 ] [ 1 ] dp[u][i][0][0]∗dp[v][j][1][1] dp[u][i][0][0]dp[v][j][1][1]

因此
d p [ u ] [ i + j ] [ 0 ] [ 1 ] = ∑ ( d p [ u ] [ i ] [ 0 ] [ 1 ] ∗ ( d p [ v ] [ j ] [ 0 ] [ 1 ] + d p [ v ] [ j ] [ 1 ] [ 1 ] ) + d p [ u ] [ i ] [ 0 ] [ 0 ] ∗ d p [ v ] [ j ] [ 1 ] [ 1 ] ) dp[u][i+j][0][1]=∑(dp[u][i][0][1]∗(dp[v][j][0][1]+dp[v][j][1][1])+dp[u][i][0][0]∗dp[v][j][1][1]) dp[u][i+j][0][1]=(dp[u][i][0][1](dp[v][j][0][1]+dp[v][j][1][1])+dp[u][i][0][0]dp[v][j][1][1])

如果u既放了装置又被监听,同样要分两种情况:

u侧的状态是 d p [ u ] [ i ] [ 1 ] [ 0 ] dp[u][i][1][0] dp[u][i][1][0],需要让v来监听u,但是v是否被监听无所谓,因为u上放了装置可以保证v被监听,所以贡献是
d p [ u ] [ i ] [ 1 ] [ 0 ] ∗ ( d p [ v ] [ j ] [ 1 ] [ 0 ] + d p [ v ] [ j ] [ 1 ] [ 1 ] ) dp[u][i][1][0]∗(dp[v][j][1][0]+dp[v][j][1][1]) dp[u][i][1][0](dp[v][j][1][0]+dp[v][j][1][1])

u侧的状态是 d p [ u ] [ i ] [ 1 ] [ 1 ] dp[u][i][1][1] dp[u][i][1][1],这时候u的所有要求都满足了,v怎么样都行,贡献是
d p [ u ] [ i ] [ 1 ] [ 1 ] ∗ ( d p [ v ] [ j ] [ 0 ] [ 0 ] + d p [ v ] [ j ] [ 0 ] [ 1 ] + d p [ v ] [ j ] [ 1 ] [ 0 ] + d p [ v ] [ j ] [ 1 ] [ 1 ] ) dp[u][i][1][1]∗(dp[v][j][0][0]+dp[v][j][0][1]+dp[v][j][1][0]+dp[v][j][1][1]) dp[u][i][1][1](dp[v][j][0][0]+dp[v][j][0][1]+dp[v][j][1][0]+dp[v][j][1][1])

因此
d p [ u ] [ i + j ] [ 1 ] [ 1 ] = ∑ ( d p [ u ] [ i ] [ 1 ] [ 0 ] ∗ ( d p [ v ] [ j ] [ 1 ] [ 0 ] + d p [ v ] [ j ] [ 1 ] [ 1 ] ) + d p [ u ] [ i ] [ 1 ] [ 1 ] ∗ ( d p [ v ] [ j ] [ 0 ] [ 0 ] + d p [ v ] [ j ] [ 0 ] [ 1 ] + d p [ v ] [ j ] [ 1 ] [ 0 ] + d p [ v ] [ j ] [ 1 ] [ 1 ] ) ) dp[u][i+j][1][1]=∑(dp[u][i][1][0]∗(dp[v][j][1][0]+dp[v][j][1][1])+dp[u][i][1][1]∗(dp[v][j][0][0]+dp[v][j][0][1]+dp[v][j][1][0]+dp[v][j][1][1])) dp[u][i+j][1][1]=(dp[u][i][1][0](dp[v][j][1][0]+dp[v][j][1][1])+dp[u][i][1][1](dp[v][j][0][0]+dp[v][j][0][1]+dp[v][j][1][0]+dp[v][j][1][1]))

这篇关于洛谷 P4516 潜入行动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/840878

相关文章

高精度计算(代码加解析,洛谷p1601,p1303)除法待更新

目录 高精度加法 高精度减法 高精度乘法 高精度加法 我们知道在c++语言中任何数据类型都有一定的表示范围。当两个被加数很大时,正常加法不能得到精确解。在小学,我们做加法都采用竖式方法。那么我们也只需要按照加法进位的方式就能得到最终解。 8 5 6+ 2 5 5-------1 1 1 1 加法进位: c[i] = a[i] + b[i];if(c[i] >=

洛谷 凸多边形划分

T282062 凸多边形的划分 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 先整一个半成品,高精度过两天复习一下补上 #include <iostream>#include <algorithm>#include <set>#include <cstring>#include <string>#include <vector>#include <map>

能量项链,洛谷

解释:  环形dp问题还是考虑将环拉直,可以参考我上一篇文章:环形石子合并 [2 3 5 10 2] 3 5 10 将环拉直,[]内是一个有效的区间,可以模拟吸收珠子的过程,         如[2 3 5] <=>(2,3)(3,5)    2是头,3是中间,5是尾 len >= 3:因为最后[2 10 2]是最小的可以合并的有效区间 len <= n + 1因为[2 3

洛谷P5490扫描线

0是最小的数字,将一个线段看成一个区间,对于一个矩形,从下扫到上,入边为1,而出边为-1,意思是将这个区间上的所有点加1(区间修改).把线段表示为Line[i],其中记录了l,r,h,tag,左右端点,高度,入边还是出边(1或-1) 那么每次区间修改后不为0的区间它的值可能是1,2,3或者是其它数字,这不好统计,可以将它转化一下,0是不是表示没有被覆盖过的地方,我们只要统计0的个数然后用总长减去

挤牛奶洛谷uasco

题目描述 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒。第二个农民在700秒开始,在 1200秒结束。第三个农民在1500秒开始2100秒结束。期间最长的至少有一个农民在挤奶的连续时间为900秒(从300秒到1200秒),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300秒(从1200秒到1500秒)。

洛谷刷题(7)

P8738 [蓝桥杯 2020 国 C] 天干地支 题目描述 古代中国使用天干地支来记录当前的年份。 天干一共有十个,分别为:甲(jiǎ)、乙(yǐ)、丙(bǐng)、丁(dīng)、戊 (wù)、己(jǐ)、庚(gēng)、辛(xīn)、壬(rén)、癸(guǐ)。 地支一共有十二个,分别为:子(zǐ)、丑(chǒu)、寅(yín)、卯(mǎo)、辰(chén)、巳(sì)、午(wǔ)、

网络价格管控行动:四大策略,打击低价

网络价格管控的举措 设定最低售价约束:品牌方能够与在线零售商订立协议,清晰界定产品的最低售价,以守护品牌形象与市场秩序。推行动态定价策略:依照市场需求、竞争态势以及库存状况动态调节产品价格,保障市场竞争力并防止库存积压。构建官方销售途径:借助官方电商平台或者自建网上商城直接面向消费者开展销售,缩减中间环节,降低销售成本,更优地掌控产品价格。加大监管与惩罚力度:针对违背价格管控规定的零售商施行警告

C++ 洛谷 哈希表(对应题库:哈希,hash)习题集及代码

马上就开学了,又一个卷季,不写点东西怎么行呢?辣么,我不准备写那些dalao们都懂得,熟练的,想来想去,最终还是写哈希表吧!提供讲解&题目&代码解析哦! 奉上题目链接: 洛谷题目 - 哈希,hash 1、哈希、哈希表(hash)简介 哈希(Hash)是一种将任意长度的输入映射为固定长度输出的算法。哈希函数的输出值称为哈希值或散列值。哈希函数具有以下特性: 确定性:对于相同的输入

Steam遭攻击崩溃!《黑神话:悟空》无法进入! 德迅云安全:或为有组织的网络攻击行动,如何有效防止DDoS攻击!

8月24日晚,《黑神话:悟空》发行平台Steam因遭到大规模DDoS攻击突然崩溃,近60个僵尸网络主控、一夜发起28万次攻击、暴涨2万多倍的事件解读。8月28日,基于大网威胁感知系统,继续对外公布本次DDoS攻击的更多技术细节,报告摘要如下:   1、此次攻击瞄准全球各时区玩家在线的高峰时段。主要分4个批次、追着时区打,分别是东半球周六中午、东半球周六晚间、西半球周六晚间和欧洲地区周日晚间、都是

洛谷p2236彩票题解

题目描述 某地发行一套彩票。彩票上写有 1 到 M 这 M 个自然数。彩民可以在这 M 个数中任意选取 N 个不同的数打圈。每个彩民只能买一张彩票,不同的彩民的彩票上的选择不同。 每次抽奖将抽出两个自然数 X 和 Y。如果某人拿到的彩票上,所选 N 个自然数的倒数和,恰好等于 X/Y,则他将获得一个纪念品。 已知抽奖结果 X 和 Y。现在的问题是,必须准备多少纪念品,才能保证支付所有获奖者的