HDU 4661 Message Passing 【Tree】
题意:
给一棵树,每一个结点都有一个信息,每一个时刻,某一对相邻的结点之间可以传递信息,那么存在一个最少的时间,使得所有的节点都可以拥有所有的信息。但是,题目不是求最短时间,而是求最短时间的情况下,有多少种传递方式:某一时刻传递信息的双方不一样则认为是不同的传递方式。(表述的不是很清楚,自己看原题了)
容易的出,最短的时间内,当然是每个节点将自己的信息想外传出去一次,并且接受一次信息,也就是树边的2倍【2*(n-1)】。
然后可以证明,在最短时间内,所有的传递方式都有一个“信息转换点”——其他节点的信息首先传递到此节点,然后信息再从这个节点向其他节点传递。
那么总方案数的计算就是可以枚举每个节点,将这个节点作为根节点,然后求当前情况下的方案——先求以当前节点为根的拓扑排序数,然后平方就是当前方案数。
拓扑排序数的计算方法:
c[i] 表示以i为根的子树的节结点(包含结点 i)
f[i] 表示以i为根的子树的拓扑排序数
则:当前结点now的拓扑排序数:
f[now] = f[son1]*f[son2]....f[sonx] * (c[now] - 1)! / (c[son1]! * c[son2]! * ... c[sonx]!)
即:所有子结点的排列数除以每颗子树所有结点的排列数(去重,对于子树的每一种拓扑序),然后乘以所有子树的拓扑序总数。
一遍dfs之后,就可以求出根节点的f值,然后在一边dfs,就可以依次求出所有节点的f值。
转移方法:
根据父节点的f值计算出去掉当前now节点之后的f值,然后以now为根节点,重新计算即可。看代码实现了。
这里用到了逆元,整个程序的速度有点慢。求逆元可以用扩展欧几里得算法,这里用的是费马定理,快速幂:x^(P-2)%P 就是x的逆元。
还有就是树dp,要避免用递归,但是还是用了,会爆栈的,所以就用手工栈了。
手工栈的方法:http://blog.csdn.net/yang_7_46/article/details/9853061
//#pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
#define N 1000002
#define P 1000000007ll ll fac[N], f[N], ff[N], cc[N], ans;
vector<int> g[N];
int n, c[N]; ll PowerMod(ll a, ll b, ll k) {
ll tmp = a, ret = 1;
while (b) {
if (b & 1) ret = ret * tmp % k;
tmp = tmp * tmp % k;
b >>= 1;
}
return ret;
} void dfs1(int now, int fa) {
int u;
c[now]++;
for (int i=0; i<g[now].size(); i++)
if ((u = g[now][i]) != fa) {
dfs1(u, now);
c[now] += c[u];
} ff[now] = cc[now] = 1;
for (int i=0; i<g[now].size(); i++)
if ((u=g[now][i]) != fa) {
ff[now] = ff[now]*f[u] % P;
cc[now] = cc[now]*fac[c[u]] % P;
}
f[now] = (ff[now]*fac[c[now]-1]%P) * PowerMod(cc[now], P-2, P) % P;
} void dfs2(int now, int fa) {
int u; ll t;
if (now != 1) {
t = f[now]*(n-c[now])%P*cc[now]%P;
t = PowerMod(t, P-2, P);
f[now] = f[fa]*ff[now]%P*fac[c[now]]%P*t%P;
ans = (ans + f[now]*f[now]) % P;
}
for (int i=0; i<g[now].size(); i++)
if ((u = g[now][i]) != fa) dfs2(u, now);
} int main() {
int size = 256 << 20; // 256MB
char *p = (char*)malloc(size) + size;
__asm__("movl %0, %%esp\n" :: "r"(p)); fac[0] = 1; for (int i=1; i<N; i++) fac[i] = fac[i-1]*i % P; int T; scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i=0; i<=n; i++) { c[i] = 0; g[i].clear(); }
for (int i=1, x, y; i<n; i++) {
scanf("%d%d", &x, &y);
g[x].push_back(y); g[y].push_back(x);
}
dfs1(1, 0);
ans = f[1] * f[1] % P;
dfs2(1, 0); printf("%I64d\n", ans);
} return 0;
}
HDU 4661 Message Passing 【Tree】的更多相关文章
- hdu 4661 Message Passing(木DP&组合数学)
Message Passing Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Other ...
- HDU 4661 Message Passing ( 树DP + 推公式 )
参考了: http://www.cnblogs.com/zhsl/archive/2013/08/10/3250755.html http://blog.csdn.net/chaobaimingtia ...
- Message Code 【27796】 Failed to connect to server 'hostname';port_ld': 'reason'.
Message Code [27796] Failed to connect to server 'hostname';port_ld': 'reason'.Unable to connect to ...
- HDU 5948 Thickest Burger 【模拟】 (2016ACM/ICPC亚洲区沈阳站)
Thickest Burger Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- HDU 5938 Four Operations 【贪心】(2016年中国大学生程序设计竞赛(杭州))
Four Operations Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...
- HDU 5920 Ugly Problem 【模拟】 (2016中国大学生程序设计竞赛(长春))
Ugly Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tota ...
- HDU 5873 Football Games 【模拟】 (2016 ACM/ICPC Asia Regional Dalian Online)
Football Games Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- HDU 3916 Sequence Decomposition 【贪心】
这道题目的题意就是使用题目中所给的Gate 函数,模拟出输入的结果 当然我们分析的时候可以倒着来,就是拿输入去减 每次Gate 函数都会有一个有效范围 这道题目求的就是,找出一种模拟方法,使得最小的有 ...
- UVA 213 Message Decoding 【模拟】
题目链接: https://cn.vjudge.net/problem/UVA-213 https://uva.onlinejudge.org/index.php?option=com_onlinej ...
随机推荐
- 如何使用getopt()函数解析参数
最近在写程序的过程中,把一部分时间都花费在程序对参数的处理上.今天听了学长说到getopt函数,才发现原来c里面还有一个专门解决参数处理的函数,查询了相关资料,这里简单总结一下. 使用int main ...
- 识别Json字符串并分隔成Map集合
识别Json字符串并分隔成Map集合 前言: 最近又看了点Java的知识,于是想着把CYQ.Data V5迁移到Java版本. 过程发现坑很多,理论上看大部分很相似,实践上代码写起来发现大部分都要重新 ...
- 经典排序算法(Java实现)
以下程序均将数据封装于DataWrap数据包装类中,如下所示: //数据包装类 class DataWrap implements Comparable<DataWrap> { int d ...
- Struts2 自定义拦截器实例—登陆权限验证
实现一个登陆权限验证的功能 message.jsp: <body> message:${message } </body> login.jsp: <% request.g ...
- const和define的区别
1.在使用const定义常量时,只能使用标量初始化; 但我们可以使用任何表达式初始化define定义的常量 2.我们可以在条件表达式中使用define定义常量,但绝对不能使用const eg: def ...
- java多线程(同步与死锁问题,生产者与消费者问题)
首先我们来看同步与死锁问题: 所谓死锁,就是A拥有banana.B拥有apple. A对B说:你把apple给我.我就把banana给你. B对A说:你把banana给我,我就把apple给你. 可是 ...
- 响应式内容滑动插件bxSlider
bxSlider特性 1.充分响应各种设备,适应各种屏幕: 2.支持多种滑动模式,水平.垂直以及淡入淡出效果: 3.支持图片.视频以及任意html内容: 4.支持触摸滑动: 5.支持Firefox,C ...
- SecureCRT 绝佳配色方案, 保护你的眼睛(转发)
SecureCRT 绝佳配色方案, 保护你的眼睛 关键词:SecureCRT配色, SecureCRT设置颜色, Linux终端配色,Linux终端颜色设置. 终端有一个好的配色,不仅能保护自己的眼睛 ...
- android入门——BroadCast(1)
使用广播要定义一个广播接收类,如 package com.example.wkp.broadcast; import android.content.BroadcastReceiver; import ...
- java:添加一条数据到数据库中文乱码
在数据库链接地址后面加上:characterEncoding=UTF8 如:jdbc\:mysql\://localhost\:3306/db_sjzdaj?relaxAutoCommit=true& ...