zoukankan      html  css  js  c++  java
  • HDU-4661 Message Passing 树形DP,排列组合

      题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4661

      题意:有n个人呈树状结构,每个人知道一个独特的消息。每次可以让一个人将他所知的所有消息告诉和他相邻的人。求所有人都知道所有消息花时花的步数最少的所有方案数。

      首先需要满足的是最小的步数,所以我们一定是先把所有消息先传到一个人手中才是最优的,然后再从这个人传回去,也就是每条边走两次。我们只需要考虑单向传到某个人的方案数cnt,因为再传回去也是cnt。那么我们可以枚举每个点为收集点,把所有的和加起来就是答案。这里就是一个树形DP的问题,转移的时候是一个组合问题:记录f[u],cnt[u],f[u]为以u为根的子树的拓扑排序数,cnt[u]为以u为子树的节点个数。这里,涉及到如何合并两个子树,比如u的两个子树v1,v2,那么合并后的拓扑排序数为:f[u]=f[son1]*f[son2]*C(cnt[son1]+cnt[son2],cnt[son1]),也就是:

      这里只求出了根节点的方案,还要再做一次搜索,把其它点的方案求出了,根据上面那个公式推一下就可以了。。。

      1 //STATUS:C++_AC_3062MS_49796KB
      2 #include <functional>
      3 #include <algorithm>
      4 #include <iostream>
      5 //#include <ext/rope>
      6 #include <fstream>
      7 #include <sstream>
      8 #include <iomanip>
      9 #include <numeric>
     10 #include <cstring>
     11 #include <cassert>
     12 #include <cstdio>
     13 #include <string>
     14 #include <vector>
     15 #include <bitset>
     16 #include <queue>
     17 #include <stack>
     18 #include <cmath>
     19 #include <ctime>
     20 #include <list>
     21 #include <set>
     22 #include <map>
     23 using namespace std;
     24 #pragma comment(linker,"/STACK:102400000,102400000")
     25 //using namespace __gnu_cxx;
     26 //define
     27 #define pii pair<int,int>
     28 #define mem(a,b) memset(a,b,sizeof(a))
     29 #define lson l,mid,rt<<1
     30 #define rson mid+1,r,rt<<1|1
     31 #define PI acos(-1.0)
     32 //typedef
     33 typedef __int64 LL;
     34 typedef unsigned __int64 ULL;
     35 //const
     36 const int N=1000010;
     37 const int INF=0x3f3f3f3f;
     38 const LL MOD=1000000007,STA=8000010;
     39 const LL LNF=1LL<<55;
     40 const double EPS=1e-9;
     41 const double OO=1e30;
     42 const int dx[4]={-1,0,1,0};
     43 const int dy[4]={0,1,0,-1};
     44 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
     45 //Daily Use ...
     46 inline int sign(double x){return (x>EPS)-(x<-EPS);}
     47 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
     48 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
     49 template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
     50 template<class T> inline T Min(T a,T b){return a<b?a:b;}
     51 template<class T> inline T Max(T a,T b){return a>b?a:b;}
     52 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
     53 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
     54 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
     55 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
     56 //End
     57 
     58 LL fac[N],rev[N],f[N],cnt[N];
     59 int T,n;
     60 LL ans;
     61 vector<int> q[N];
     62 
     63 void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
     64 {
     65     if(!b){d=a;x=1;y=0;}
     66     else {exgcd(b,a%b,d,y,x);y-=x*(a/b);}
     67 }
     68 
     69 LL inv(LL a,LL n)
     70 {
     71     LL d,x,y;
     72     exgcd(a,n,d,x,y);
     73     return (x+n)%n;
     74 }
     75 
     76 void dfs1(int u,int fa)
     77 {
     78     int i,v;
     79     cnt[u]=f[u]=1;
     80     for(i=0;i<q[u].size();i++){
     81         if((v=q[u][i])==fa)continue;
     82         dfs1(v,u);
     83         cnt[u]+=cnt[v];
     84         f[u]=((f[u]*f[v])%MOD*rev[cnt[v]])%MOD;
     85     }
     86     f[u]=(f[u]*fac[cnt[u]-1])%MOD;
     87 }
     88 
     89 void dfs2(int u,int fa)
     90 {
     91     int i,v;
     92     if(u!=1){
     93         f[u]=(f[fa]*cnt[u])%MOD*inv(n-cnt[u],MOD)%MOD;
     94         ans=(ans+f[u]*f[u]%MOD)%MOD;
     95     }
     96     for(i=0;i<q[u].size();i++){
     97         if((v=q[u][i])==fa)continue;
     98         dfs2(v,u);
     99     }
    100 }
    101 
    102 int main(){
    103  //   freopen("in.txt","r",stdin);
    104     int i,j,a,b;
    105     fac[0]=1;
    106     for(i=1;i<N;i++)fac[i]=(i*fac[i-1])%MOD;
    107     for(i=1;i<N;i++)rev[i]=inv(fac[i],MOD);
    108     scanf("%d",&T);
    109     while(T--)
    110     {
    111         scanf("%d",&n);
    112         for(i=1;i<=n;i++)q[i].clear();
    113         for(i=1;i<n;i++){
    114             scanf("%d%d",&a,&b);
    115             q[a].push_back(b);
    116             q[b].push_back(a);
    117         }
    118 
    119         dfs1(1,0);
    120         ans=f[1]*f[1]%MOD;
    121         dfs2(1,0);
    122 
    123         printf("%I64d
    ",(ans+MOD)%MOD);
    124     }
    125     return 0;
    126 }
  • 相关阅读:
    setCapture 适用范围
    移动web页面自动探测电话号码
    WEB页面JS实现一键拨号的电话拨打功能
    highcharts动态删除标示区
    【你不知道的JavaScript
    【你不知道的JavaScript
    【JavaScipt高级程序设计 第4版】第5章笔记 日期格式
    【JavaScipt高级程序设计 第4版】第6章笔记 Map Set
    【JavaScipt高级程序设计 第4版】第6章笔记 Array 集合引用类型
    【JavaScipt高级程序设计 第4版】第4章笔记
  • 原文地址:https://www.cnblogs.com/zhsl/p/3250755.html
Copyright © 2011-2022 走看看