hihoCoder #1471 拥堵的城市
这道题目是hihoCoder Challenge 27的C题,我考虑了5天:(。
计数问题。由于树的结构的特殊性(树具有递归结构),不难想到思路是树形DP。由于这是【计数问题】而非【优化问题】,我们思考时应该着重考虑两个基本的计数原理:加法原理与乘法原理,而非所谓【最优子结构】。
DP 状态
关于DP状态设计,我的思考过程如下:
指定一节点作为根,转化成有根树。我们考虑子问题:
子树 $v$ 中的路线方案数。
然后考虑
将子树 $v$ 中的所有可能的方案压缩到一个怎样的子空间中能实现从(子树) $v$ 到其父节点 (子树)$u$ 的状态转移?
DP状态要有助于计算通过 $u$ 的路线的方案数。而这样的路线由任意两不同的自由节点(非路线端点) $v_1$、$v_2 \text{ s.t. } \text{LCA}(v_1,v_2) = u$ 所确定。
状态1
$dp[i][j]$:子树 $i$ 中有 $j$ 个自由点的方案数。
然而这 $j$ 个自由点到点 $i$ 的路径在【任意一条边最多被 $k$ 条路线经过】的限制下可能互斥。
状态2
在 $dp[i][j]$: 从子树 $i$ 中选择 $j$ 条【独立路径】伸出来的方案数。
这个状态是可以转移的。这里需要指出的一点是,我们不采用类似于 “子树 $i$ 中有 $j$ 条独立路径伸出来” 这样的表述来定义状态,而采用 “选择” 这个词。
转移方程
同大多数树形 DP 一样,状态转移是一个合并子树的过程。在计算子树 $u$ 中的方案数的过程中,对于 $u$ 的儿子 $v$,将子树 $v$ 的状态合并到子树 $u$ 中的方法:
枚举从子树 $v$ 中选出的【用于和前面的独立路径配对的独立路径】的数目 $x$ 和【不配对的独立路径】的数目 $y$
Implementation
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int mod = 1e9+7;
const int N = 305;
vector<int> g[N];
int size[N];
int dp[N][N];
void add_mod(int &x, int y)
{
x += y;
if(x >= mod)
x -= mod;
}
int f[N]{1};
int c[N][N];
void prep(int n)
{
for(int i=1; i<=n; ++i)
f[i]=ll(f[i-1])*i%mod;
for(int i=0; i<=n; i++)
c[i][0] = 1;
for(int i=1; i<=n; i++)
for(int j=1; j<=i; j++)
add_mod(c[i][j], c[i-1][j-1]), add_mod(c[i][j], c[i-1][j]);
}
int cur[N];
int n, k;
void dfs(int u, int fa)
{
size[u] = 1;
dp[u][0] = 1;
dp[u][1] = 1;
for(auto &v: g[u])
{
if(v != fa)
{
dfs(v, u);
for(int x=0; x <= min(size[v], k); ++x) // pair
{
for(int y=0; x+y <= min(size[v], k); ++y) // single
{
int tmp = ll(dp[v][x+y]) * c[x+y][y] % mod;
if(tmp == 0)
continue;
for(int i=x; i<=size[u]; ++i)
{
add_mod(cur[i-x+y], ll(tmp) * dp[u][i] % mod * c[i][x] % mod * f[x] % mod); // error-prone
}
}
}
size[u] += size[v];
for(int i=0; i<=size[u]; ++i)
{
dp[u][i] = cur[i];
cur[i] = 0;
}
}
}
}
int main()
{
scanf("%d%d", &n, &k);
prep(n);
for(int i=1; i<n; i++)
{
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 1);
printf("%d\n", dp[1][0]);
return 0;
}
要格外注意递归函数中的全局变量。
总结
前两天在知乎上看到一个解释【DP状态的无后效性】的回答,思考这个问题的过程中感到很受用。
一般我们说的最优解问题,最朴素的做法是搜索所有的方案,大部分时候这个复杂度是不能接受的。对某些问题来说,我们可以将问题分解成子问题,子问题具有最优子结构的特点:对子问题的优化可以带来对整个问题的优化。但仅仅是这样并没有很大的帮助,因为我们对子问题的优化可能会导致整个问题的其他部分的解法变得不成立,或者变得不够优化,这样我们仍然不能有效计算整个问题的最优解。但是,某些情况下,子问题对于整个问题的影响,可以归纳到一个比“所有子问题解法”的空间小得多的“子问题状态”空间中,只要子问题解决后的状态处于某个状态,它对于整个问题的影响就是一致的,这样如果已知子问题处于某个状态,我们就可以求出这个状态条件下子问题的最优解,当全局最优且这个子问题取这个状态时,子问题本身的解法一定是我们刚刚求出的最优解。这样我们只需要对每个子问题的每个状态计算最优解,然后通过这些最优解的递推关系就可以求出整个问题的最优解。这种子问题对主问题的影响可以总结为少数“状态”的特性就叫做无后效性,意味着只要状态一致,具体经过怎样的步骤到达这一状态是没有影响的。
SOURCE
hihoCoder #1471 拥堵的城市的更多相关文章
- 天气预报API(二):全球城市、景点代码列表(“旧编码”)
说明 2016-12-10 补充 (后来)偶然发现中国天气网已经有城市ID列表的网页...还发现城市编码有两种,暂且称中国天气网这些编码为旧标准"旧编码"的特征是 9个字符长度; ...
- 【hihoCoder】1041. 国庆出游
问题:详见http://hihocoder.com/problemset/problem/1041 有n个城市,城市编号为1-n,城市间有n-1条路(所以,城市路网是一棵树).给定一个序列S,要求判断 ...
- 基于tp框架实现的递归城市查询
控制器层: 接下来就是模型层: 如果说你的数据量庞大到致使apache或者nginx停止运行,有两点原因: 1.代码耦合性不高,代码有错误: 2.php.ini里面有一个memory_limit的这个 ...
- JQUERY省、市、县城市联动选择
JQUERY 插件开发——CITYLINKAGE(省.市.县城市联动选择) 第一部分:背景 开发源于需求,本次城市联动选择插件算是我写插件的一个特例吧,不是我目前工作需要些的,算是兴趣驱使吧.之前 ...
- VR全景智慧城市常诚:信息技术点亮“智慧城市”
亚太城市峰会暨市长论坛日前在澳大利亚昆士兰州首府布里斯班举行,"智慧城市"成为焦点议题.来自135个国家和地区的市长.副市长及代表们共同讨论如何利用高新科技解决城市发展中的问题,让 ...
- 全国地区的省份、城市、区县 最新Sql脚本
IF (EXISTS(SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TB_Province]') AND type =' ...
- 最新!2016中国城市GDP排名出炉
2017年1月20日,国家统计局公布:2016年中国国内生产总值GDP达744127亿元,同比增长6.7%,城市GDP方面:截至1月20日,全国大部分城市的去年经济运行数据已经公布,根据信息汇总,20 ...
- Jquery 插件开发——citylinkage(省、市、县城市联动选择)
第一部分:背景 开发源于需求,本次城市联动选择插件算是我写插件的一个特例吧,不是我目前工作需要些的,算是兴趣驱使吧.之前呢,一直想写这个插件,然后错过了一个写这个插件的机会(这个得回顾到很久以前了. ...
- AI-Info-Micron-Insight:V2X 自主性:帮助减少事故、排放和交通拥堵
ylbtech-AI-Info-Micron-Insight:V2X 自主性:帮助减少事故.排放和交通拥堵 1.返回顶部 1. V2X 自主性:帮助减少事故.排放和交通拥堵 一辆汽车冲到你的车道上.晚 ...
随机推荐
- cvLoadImage,cvCloneImage的内存泄露问题
本文转自: http://hi.baidu.com/%C3%A8%D1%DB%D3%E3/blog/item/9d947e1b2b05555742a9adfd.html/cmtid/9872c2260 ...
- Drools应用实例
Drools 实例介绍 Drools编译与运行: 在Drools当中,规则的编译与运行要通过Drools提供的各种API来实现,这些API总体来讲可以分为三类:规则编译.规则收集和规则的执行. Kmo ...
- 解决Errno::ENOENT: No Such File or Directory - Jekyll ~ Octopress and El Capitan
参考http://schalkneethling.github.io/blog/2015/10/16/errno-enoent-no-such-file-or-directory-jekyll-oct ...
- 阿里Java架构师面试高频300题:集合+JVM+Redis+并发+算法+框架等
前言 在过2个月即将进入9月了,然而面对今年的大环境而言,跳槽成功的难度比往年高了很多,很明显的感受就是:对于今年的java开发朋友跳槽面试,无论一面还是二面,都开始考验一个Java程序员的技术功底和 ...
- Bootstrap历练实例:表单控件状态(禁用的字段集fieldset)
禁用的字段集 fieldset 对 <fieldset> 添加 disabled 属性来禁用 <fieldset> 内的所有控件. <!DOCTYPE html>& ...
- javaEE(12)_数据库连接池
一.直接获取数据库连接和通过池获取示意图: 二.编写数据库连接池 1.实现DataSource接口,并实现连接池功能的步骤: •在DataSource构造函数中批量创建与数据库的连接,并把创建的连接加 ...
- javaEE(4)_response、request对象
一.简介 Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象.request和response对象即然代表请求和响应 ...
- iOS7.1企业版发布后用户通过sarafi浏览器安装无效的解决方案
关于iOS7.1企业版发布后,用户通过sarafi浏览器安装无效的解决方案: 通过测试,已经完美解决. 方案一: iOS7.1企业应用无法安装应用程序 因为证书无效的解决方案 http://blog. ...
- 【树形dp】vijos1144小胖守皇宫
细节很精妙 描述 huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫. 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状:某些宫殿间可以互相望见.大内保卫森严,三步一岗,五步 ...
- virtualenvwrapper.sh报错: There was a problem running the initialization hooks.解决
由于在ubuntu环境下,将python做与python3.6做了软链接(ln -s python python3.6),并且pip也被我做了软链接,所以导致用pip安装virtualenvwrapp ...