Hdu-4661 Message Passing(树形DP)
来源:互联网 发布:东方有线网络缴费 编辑:程序博客网 时间:2024/05/18 04:29
There are n people numbered from 1 to n. Each people have a unique message. Some pairs of people can send messages directly to each other, and this relationship forms a structure of a tree. In one turn, exactly one person sends all messages s/he currently has to another person. What is the minimum number of turns needed so that everyone has all the messages?
This is not your task. Your task is: count the number of ways that minimizes the number of turns. Two ways are different if there exists some k such that in the k-th turn, the sender or receiver is different in the two ways.
This is not your task. Your task is: count the number of ways that minimizes the number of turns. Two ways are different if there exists some k such that in the k-th turn, the sender or receiver is different in the two ways.
Following are T test cases.
For each test case, the first line is number of people, n. Following are n-1 lines. Each line contains two numbers.
Sum of all n <= 1000000.
221 231 22 3
26
题意:n个人构成一棵树,每个人有一个独特的信息,每轮最多有一个人把他携带的所有信息传递给和他相邻的人,假如最多传k轮所有人都能得到所有信息,问方案数有多少.
分析:考虑树上的每条边,可以看作有两个方向,那么每条边最多传入一次传出一次,所以最少传递次数的上限为2*(n-1),然后我们可以轻易的构造出来这种方案,只要选一个点为根每次都先通过n-1把所有的信息都传入给他,再通过n-1次将这个信息传回所有点就可以了,然后我们考虑如何统计方案,考虑每个点都作为一次汇点,假如传入a的方案数为f(a),那么我们可以根据一一对应的法则证明从a传出去的方案数也为f(a),所以最后的答案就是sigma(f(a)^2),f(a)可以用树形dp求出来,具体就是先随便找一个点作为根,然后dfs这棵树并且求出来每个点的子树符合拓扑序的所有方案数,然后再dfs一次求出以每个点为汇点的方案数.
#include <bits/stdc++.h>#define INF 1000111111#define N 1000005#define MOD 1000000007using namespace std;typedef long long ll;int T,n,x,y;ll ans,gc[N],igc[N],Ans[N],Down[N],Size[N];vector<int> G[N];void exgcd(ll a,ll b,ll &g,ll &x,ll &y){ if(!b) g=a,x=1,y=0; else { exgcd(b,a%b,g,y,x); y-=a/b*x; }}ll inv(ll a,ll n){ ll d,x,y; exgcd(a,n,d,x,y); return d == 1 ? (x+n)%n : -1;}ll c(int x,int y){ return (gc[x]*igc[y] % MOD)*igc[x-y] % MOD;}void dfs1(int u,int fa){ Size[u] = 1,Down[u] = 1; for(int v : G[u]) if(v != fa) { dfs1(v,u); Size[u] += Size[v]; if(!Down[u]) Down[u] = Down[v]; else Down[u] = (Down[u]*Down[v] % MOD)*c(Size[u] - 1,Size[v]) % MOD; }}void dfs2(int u,int fa){ if(u == 1) Ans[u] = Down[u]; else { ll res = (Ans[fa]*inv(Down[u],MOD) % MOD)*inv(c(n-1,Size[u]),MOD) % MOD; Ans[u] = (c(n-1,Size[u]-1)*Down[u] % MOD)*res % MOD; } ans = (ans + Ans[u]*Ans[u] % MOD) % MOD; for(int v : G[u]) if(v != fa) dfs2(v,u);}int main(){ gc[0] = igc[0] = 1; for(int i = 1;i < N;i++) gc[i] = (gc[i-1]*i) % MOD; for(int i = 1;i < N;i++) igc[i] = inv(gc[i],MOD); scanf("%d",&T); while(T--) { ans = 0; scanf("%d",&n); for(int i = 1;i <= n;i++) G[i].clear(); for(int i = 1;i < n;i++) { scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } dfs1(1,1); dfs2(1,1); cout<<ans<<endl; }}
阅读全文
0 0
- hdu 4661 Message Passing(树形dp)
- hdu 4661 Message Passing(树形dp)
- hdu 4661 Message Passing - 树形dp
- hdu 4661 Message Passing(树形dp)
- Hdu-4661 Message Passing(树形DP)
- Hdu 4661 Message Passing(树形DP,扩展欧几里得)
- hdu 4661 Message Passing 树形dp (2013多校联合)
- hdu 4661 Message Passing(树形DP&组合数学)
- 2013 多校第六场 hdu 4661 Message Passing(树形DP+拓展欧几里得)
- HDU 4661 Message Passing
- hdu 4661Message Passing
- HDU 4661 Message Passing
- HDU 4661 Message Passing 【Tree】
- 逆元+树形dp-memset-hdu4661-Message Passing
- hdu 4661 Message Passing (思维 dp求拓扑排序数)
- HDOJ 4661: Message Passing
- HDU 3410Passing the Message
- HDU 3410 Passing the Message
- 二、java运行环境按照之-linux centos下安装jdk步骤【rpm安装方式】
- [随心译]2017.8.2-苹果的ARKit实景DEMO看起来简直不可思议
- 解决centos没有iptables的问题
- C++学习博客地址
- The Suspects POJ 1611
- Hdu-4661 Message Passing(树形DP)
- Struts2模型驱动和属性驱动
- 屈老师计算机公开课讲座笔记
- typescript中import"fs"模块
- POJ 3252 数位DP
- SDUT-Catch That Cow
- OSG 学习第二天:几何体的绘制
- Log4j简单demo及log4j.properties
- 设计的理性模型