题目传送门:

BZOJ

题意精简版:给出一棵树,在一种方案中可以将树的若干链上的所有边的边权改为$0$,但需要保证任意两条链之间没有交点。问最少的一种方案,使得从根节点到其他节点经过的边的边权和的最大值最小,并求出方案数。$N \leq 10^5$


真心火题,现在我还在想是哪个神人推出的这个DP方程

关于原题中的无解情况直接判断$M==N-1$是否成立即可,因为根据题目要求,最后生成出来的一定会是一棵树。

先考虑第二问,设$f_{i,j,k}$表示在子树$i$内,最大的边权和不超过$j$,点$i$与其$k$个儿子在一条链上的方案数。首先可以知道$k=0,1,2$,因为任意两条链之间没有交点。

接下来我们考虑$j$的取值。手玩可以发现,当一棵树是三叉树的时候,才会有一个边权的贡献,而当整棵树是深度为$h$的满二叉树的时候,才会有$h$的最大边权,而$\sum\limits_{i=0}^{10} 3^i = 8.6 \times 10^4$,所以可以知道答案会小于等于10,所以$j$的有效取值范围就在$[0,10]$中间,第一问的答案自然也就很小。

接下来考虑转移。根据乘法原理,我们可以得到这样子的式子:

$$f_{i,j,2}=f_{i,j,1} \times (f_{soni,j,0} + f_{soni,j,1}) + f_{i,j,2} \times (f_{soni,j-1,0} + f_{soni,j-1,1} + f_{soni,j-1,2})$$

$$f_{i,j,1}=f_{i,j,0} \times (f_{soni,j,0} + f_{soni,j,1}) + f_{i,j,1} \times (f_{soni,j-1,0} + f_{soni,j-1,1} + f_{soni,j-1,2})$$

$$f_{i,j,0}=f_{i,j,0} \times (f_{soni,j-1,0} + f_{soni,j-1,1} + f_{soni,j-1,2})$$

其中$soni$表示$i$的某个儿子。边界是$f_{i,j,0}=1$,其余为$0$

每一个点统计儿子的所有转移即可,复杂度为$O(33N)$。

至于第一问,可以从小到大枚举dp的第$2$维,最小的在$1$号点上方案数大于$0$的数就是答案。

注意:因为原题需要$mod\,Q$,所以如果答案$mod\,Q==0$会出现错误,推荐在某个数与$mod \, Q = 0$时将其修改为$Q$而不是$0$。

 #include<bits/stdc++.h>
 using namespace std;

 inline int read(){
     ;
     char c = getchar();
     while(!isdigit(c))
         c = getchar();
     while(isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return a;
 }

 ;
 struct Edge{
     int end , upEd;
 }Ed[MAXN << ];
 int head[MAXN] , fa[MAXN] , cntEd , N , M , Q;
 ][];
 bool vis[MAXN];

 inline void addEd(int a , int b){
     Ed[++cntEd].end = b;
     Ed[cntEd].upEd = head[a];
     head[a] = cntEd;
 }

 inline int get(long long x){
      && x % Q ==  ? Q : x % Q;
 }

 void dfs(int now){
     vis[now] = ;
      ; i <=  ; i++)
         dp[now][i][] = ;
     for(int i = head[now] ; i ; i = Ed[i].upEd)
         if(!vis[Ed[i].end]){
             fa[Ed[i].end] = now;
             dfs(Ed[i].end);
         }
      ; j <=  ; j++){
         ][] + dp[now][j - ][] + dp[now][j - ][]) , l = ] + dp[now][j][]);
         dp[fa[now]][j][] = ] * l + dp[fa[now]][j][] * k);
         dp[fa[now]][j][] = ] * k + dp[fa[now]][j][] * l);
         dp[fa[now]][j][] = ] * k);
     }
     dp[fa[now]][][] = ][] * (dp[now][][] + dp[now][][]));
     dp[fa[now]][][] = ][] * (dp[now][][] + dp[now][][]));
     dp[fa[now]][][] = ;
 }

 int main(){
     N = read();
     M = read();
     ){
         cout << "-1\n-1";
         ;
     }
     Q = read();
      ; i <= M ; i++){
         int a = read() , b = read();
         addEd(a , b);
         addEd(b , a);
     }
     dfs();
      ; i <= N ; i++){
         ][i][] + dp[][i][] + dp[][i][];
         if(sum){
             cout << i << endl << sum % Q;
             ;
         }
     }
 }

最新文章

  1. nodejs中流(stream)的理解
  2. HBASE列族不能太多的真相 (一个table有几个列族就有几个 Store)
  3. go语言的 数组、slice、map使用(转)
  4. Spring 学习笔记 8. 尚硅谷_佟刚_Spring_使用外部属性文件
  5. typedef和#define的用法与区别
  6. yum 部署nginx
  7. Codeforces Round #181 (Div. 2) C. Beautiful Numbers 排列组合 暴力
  8. 琐碎-hadoop1.X和2.X的区别
  9. c++编程思想(一)--对象导言
  10. UISearchBar的扩展使用
  11. git本机服务器配置(二):TortoiseGit的安装
  12. java核心-多线程-Java多线程编程涉及到包、类
  13. eMMC基础技术7:Bus Speed Modes
  14. Python爬虫html解析工具beautifulSoup在pycharm中安装及失败的解决办法
  15. day2:day1作业 字符编码
  16. vue脚手架用axios请求本地数据
  17. 51nod 1052 最大M子段和
  18. 关于ST-Link下载STM32程序的使用
  19. angular的uiRouter服务学习(2)
  20. IOS中Key-Value Coding (KVC)的使用详解

热门文章

  1. 数据库连接池(基于MySQL数据库)
  2. loadrunner&#160;脚本优化-事务时间简介
  3. Android项目实战(五十一):浅谈GreenDao
  4. Android为TV端助力 内存溢出与内存泄露
  5. 修改minifest使桌面软件支持高dpi
  6. codeforces 2B The least round way(DP+数学)
  7. sql server 计算两个时间 相差的 几天几时几分几秒
  8. 洗礼灵魂,修炼python(70)--爬虫篇—补充知识:json模块
  9. SQL Server 索引重建手册
  10. c/c++连通图的遍历(深度遍历/广度遍历)