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\n",(ans+MOD)%MOD);

124     }

125     return 0;

126 }

 

你可能感兴趣的:(message)