题目链接

(BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4042
(Luogu) https://www.luogu.org/problem/P4757

题解

挺神仙的题。
观察到两个重要性质:

(1) 只有不影响任何已选方案的时候,才需要去考虑是否要选择\(u\)的子树内往上走的链。(因为链不带权值)

(2) 如果要选择\(u\)子树内往上走的链,那么最多选择一条。

由此可知,我们可以记录哪些链在\(u\)子树内的所有方案中是必选的,所有非必选的都可视作空闲。因为往上走的链最多选择一条,所以如果这条链和一条非必选的边冲突,有办法调整最优方案使得这条链选上,而不会受到“两条非必选的边至少选一条”这种情况的影响。

于是我们记录\(dp[u]\)表示\(u\)子树内最多选择多少链以及\(S[u]\)表示\(u\)子树内最优解非必选的端点,转移的时候先把所有的儿子拿出来,建一个图,两点\(i,j\)连边当且仅当存在\(x\in S[i],y\in S[j], x,y\)是输入的一条路径,然后用状压DP求它的最大匹配即可。设\(dp0[i]\)表示\(i\)集合内的最大匹配,\(U\)为所有儿子的全集,那么若\(dp0[U]=dp0[U-\{i\}]\)就说明\(i\)非必选,那么把\(S[i]\)加入到\(S[u]\)中。
注意特殊处理以\(u\)为一条链的端点的情况。

时间复杂度\(O(n^2+nd2^d+m)\).

代码

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cassert>
#include<vector>
using namespace std;const int N = 1000;
const int M = 5e5;
const int D = 10;
int lg2[(1<<D)+3];
struct Edge
{int v,nxt;
} e[(N<<1)+3];
int fe[N+3];
int fa[N+3];
bool a[N+3][N+3];
vector<int> ac[N+3];
int dp[N+3];
vector<int> son;
bool ae[D+3][D+3];
bool ae0[D+3];
int dp0[(1<<D)+3];
int n,en,m;void addedge(int u,int v)
{en++; e[en].v = v;e[en].nxt = fe[u]; fe[u] = en;
}void dfs(int u)
{dp[u] = 0;for(int i=fe[u]; i; i=e[i].nxt){int v = e[i].v;if(v==fa[u]) continue;fa[v] = u;dfs(v);dp[u] += dp[v];}son.clear();for(int i=fe[u]; i; i=e[i].nxt){int v = e[i].v;if(v==fa[u]) continue;son.push_back(v);}for(int i=0; i<son.size(); i++){for(int j=i+1; j<son.size(); j++){ae[i][j] = ae[j][i] = false;for(int ii=0; ii<ac[son[i]].size(); ii++){for(int jj=0; jj<ac[son[j]].size(); jj++){if(a[ac[son[i]][ii]][ac[son[j]][jj]]){ae[i][j] = ae[j][i] = true; break;}}}}ae0[i] = false;for(int ii=0; ii<ac[son[i]].size(); ii++) {if(a[ac[son[i]][ii]][u]) {ae0[i] = true; break;}}}dp0[0] = 0;for(int i=1; i<(1<<son.size()); i++){int x = lg2[i&(-i)];dp0[i] = dp0[i^(1<<x)];if(ae0[x]) {dp0[i]++;}for(int j=0; j<son.size(); j++){if(i&(1<<j)){if(ae[x][j]) {dp0[i] = max(dp0[i],dp0[i^(1<<x)^(1<<j)]+1);}}}}dp[u] += dp0[(1<<son.size())-1];for(int i=0; i<son.size(); i++){if(dp0[(1<<son.size())-1]==dp0[((1<<son.size())-1)^(1<<i)]){for(int j=0; j<ac[son[i]].size(); j++) {ac[u].push_back(ac[son[i]][j]);}}}ac[u].push_back(u);
}int main()
{for(int i=0; i<=D; i++) lg2[1<<i] = i;int T; scanf("%d",&T);while(T--){scanf("%d",&n);for(int i=1; i<n; i++){int u,v; scanf("%d%d",&u,&v);addedge(u,v); addedge(v,u);}scanf("%d",&m);for(int i=1; i<=m; i++){int u,v; scanf("%d%d",&u,&v);a[u][v] = a[v][u] = 1;}dfs(1);printf("%d\n",dp[1]);for(int i=1; i<=n; i++) fe[i] = fa[i] = 0,ac[i].clear();for(int i=1; i<=en; i++) e[i].v = e[i].nxt = 0;for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) a[i][j] = a[j][i] = 0;n = en = m = 0;}return 0;
}

BZOJ 4042 Luogu P4757 [CERC2014]Parades (树形DP、状压DP)相关推荐

  1. 【BZOJ】1076 [SCOI2008]奖励关 期望DP+状压DP

    [题意]n种宝物,k关游戏,每关游戏给出一种宝物,可捡可不捡.每种宝物有一个价值(有负数).每个宝物有前提宝物列表,必须在前面的关卡取得列表宝物才能捡起这个宝物,求期望收益.k<=100,n&l ...

  2. [转]状态压缩dp(状压dp)

    状态压缩动态规划(简称状压dp)是另一类非常典型的动态规划,通常使用在NP问题的小规模求解中,虽然是指数级别的复杂度,但速度比搜索快,其思想非常值得借鉴. 为了更好的理解状压dp,首先介绍位运算相关的 ...

  3. [BZOJ 1879][SDOI 2009]Bill的挑战 题解(状压DP)

    [BZOJ 1879][SDOI 2009]Bill的挑战 Description Solution 1.考虑状压的方式. 方案1:如果我们把每一个字符串压起来,用一个布尔数组表示与每一个字母的匹配关 ...

  4. bzoj4455 loj2091 [Zjoi2016]小星星 容斥原理+树形DP(+状压DP?)

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4455 https://loj.ac/problem/2091 题解 很不错的一道题.(不过在当 ...

  5. 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)

    2595: [Wc2008]游览计划 Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special Judge Submit: 1572  Solved:  ...

  6. SCUT - 254 - 欧洲爆破 - 概率dp - 状压dp

    https://scut.online/p/254 思路很清晰,写起来很恶心. #include<bits/stdc++.h> using namespace std; #define l ...

  7. 天上掉馅饼 期望dp+状压dp

    天上掉馅饼 (bonus) 题目描述 小G进入了一个神奇的世界,在这个世界,天上会掉下一些馅饼.今天,天上会随机掉下k个馅饼. 每次天上掉下馅饼,小G可以选择吃或者不吃(必须在下一个馅饼掉下来之前作出 ...

  8. 状压dp个人刷题记录

    目录 一.普通型 蒙德里安的梦想 题意: 思路: code: #2153. 「SCOI2005」互不侵犯 题意: 思路: code: P1879 [USACO06NOV]Corn Fields G 题 ...

  9. 【状压DP】吃货JYY(luogu 6085)

    正题 luogu 6085 题目大意 给你一个无向图,其中有一些边是必须走的,问你从1开始走,经过所有必须走的边,然后回到1的最短路径 解题思路 n很小,可以先用Floyd跑出两个点之间的最短路 然后 ...

最新文章

  1. 在UE4中创建CG动画 How to create a movie in Unreal Engine 4 using Metahuman
  2. 【2018-01-22】HTML-表单及表单元素
  3. ST17H26开发小总结
  4. Boost正则表达式的编译与使用方法集
  5. 工厂三兄弟之简单工厂模式
  6. 通过实际的例子,介绍 SAP ABAP 里的 Repository Information System 的使用技巧
  7. CSS:页脚紧贴底部
  8. P3723 [AH2017/HNOI2017]礼物 FFT + 式子化简
  9. Ubuntu 16.04 中 安装 Docker
  10. 【快速入门Linux】5_Linux命令—远程管理常用命令
  11. SQLAlchemy Transactions
  12. 自己写的免费的音乐播放器:可以播放txt格式的音乐
  13. kettle连接ClickHouse
  14. python批量剪辑音频pydub
  15. 2021最新版成语接龙小程序源码
  16. 防劫持工具,介绍几款浏览器劫持修复工具
  17. Android通过反射EthernetManager Api设置以太网为静态IP地址或者动态获取IP
  18. Wi-Fi基带芯片和Wi-Fi无线网卡设计方案
  19. Linux常用命令——hostid命令
  20. 使用ROSE寻找超级增强子

热门文章

  1. A humble heart2019-11-09
  2. 云炬Android开发笔记 2-3Android Studio如何导入Github上的项目
  3. 用ConfigParser模块读写conf配置文件
  4. vant ui wepy_UI设计需要学习什么软件呢?
  5. [scala-spark]2. Scala运行原理与源码查看
  6. 为什么说多道程序概念得到了中断和通道技术的支持?
  7. 程序员面试系列——插入排序
  8. HashSet、TreeSet、TreeMap实现原理
  9. MPU6050开发 -- 初识
  10. S5PV210开发 -- QT4.8 移植