zoukankan      html  css  js  c++  java
  • 动态规划(DP计数):HDU 5121 Just A Mistake

    As we all know, Matt is an outstanding contestant in ACM-ICPC. Graph problems are his favorite.

    Once, he came up with a simple algorithm for finding the maximal independent set in trees by mistake.

    A tree is a connected undirected graph without cycles, and an independent set is subset of the vertex set which contains no adjacent vertex pairs.

    Suppose that the tree contains N vertices, conveniently numbered by 1,2, . . . , N. First, Matt picks a permutation p1, p2, . . . , pN of {1, 2, 3, . . . , N } randomly and uniformly.

    After picking the permutation, Matt does the following procedure.

    1.Set S = ∅.
    2.Consider the vertex p1, p2, . . . , pN accordingly. For vertex pi, if and only if there is no vertex in S which is adjacent to pi, add vertex pi into S.
    3.Output the set S.

    Clearly the above algorithm does not always output the maximal independent set. Matt would like to know the expected size of set S instead.
     

    Input

    The first line contains only one integer T , which indicates the number of test cases.

    For each test case, the first line contains an integer N (1 ≤ N ≤ 200), indicating the number of vertices in the graph.

    Each of the following N - 1 lines contains two integers u, v (1 ≤ u, v ≤ N ) indicating an edge between u and v. You may assume that all the vertices are connected.
     

    Output

    For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y is the answer. To avoid rounding error, the answer you should output is:

    (the expected size of independent set) × N! mod (109 + 7)
     

    Sample Input

    2
    4
    1 2
    1 3
    1 4
    3
    1 2
    2 3

    Sample Output

    Case #1: 60
    Case #2: 10

    Hint

    In the first sample, there are 4 vertices, so there are 4! permutations Matt may get. Suppose the permutation Matt gets is 1 2 3 4. He will add vertex 1 into the independent set. Suppose the permutation Matt gets is 2 1 3 4. He will add vertex 2, vertex 3 and vertex 4 into the independent set. It is obvious that if the first element in the permutation is not vertex 1, he will get an independent set whose size is 3. Otherwise, he well get an independent set whose size is 1. Since there are 18 permutations whose first element is not vertex 1, the answer in the first sample is (3 × 18 + 1 × 6) mod (10^9 + 7) = 60.
      好题好题,我有幸成为了HDU第12名A穿此题的人。
      这道题就是对任意1~n的排列跑题中所给的程序,得到的集合S,求sigma(|S|)。
      考虑dp,dp[x][i]表示x在当前以它为根的子树中的所有1~sz[x]的排列中位置在i,并且x被选入集合的排列数。
      枚举根节点,发现不同子树间互不影响,只有父亲与儿子之间才会有影响,现在就是dp的形式就是两组排列,相互安插,用组合数搞一搞。
      枚举to[i]这棵子树的1~sz[to[i]]的集合中前a个插在x前面,后面的sz[to[i]]-a个在x后面,乘上dp[x][i],再乘上选位置的方案,选位置的话,x个数插到y个数中,方案数是C(x+y,x)
      时刻要记得取模……         貌似我的题解是此题网络上的第一篇BLOG,好开心……
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 const int N=210,Mod=(int)1e9+7;
     6 int cnt,fir[N],to[N*2],nxt[N*2];
     7 void addedge(int a,int b){
     8     nxt[++cnt]=fir[a];to[fir[a]=cnt]=b;
     9     nxt[++cnt]=fir[b];to[fir[b]=cnt]=a;
    10 }
    11 typedef long long LL;
    12 #define clr(x) memset(x,0,sizeof(x))
    13 LL ans,dp[N][N],tmp[N],sum[N],fac[N],c[N][N];
    14 LL Inv(LL x){return x==1?1:(Mod-Mod/x)*Inv(Mod%x)%Mod;}
    15 void Prepare(){
    16     fac[0]=1;
    17     for(int i=1;i<N;i++)
    18         fac[i]=fac[i-1]*i%Mod;
    19     for(int i=0;i<N;i++)for(int j=0;j<=i;j++)
    20         c[i][j]=fac[i]*Inv(fac[j]*fac[i-j]%Mod)%Mod;
    21 }
    22 
    23 int fa[N],sz[N];
    24 void Update(int x,int y){
    25     clr(sum);clr(tmp);
    26     for(int i=1;i<=sz[y];i++)
    27         sum[i]=(sum[i-1]+dp[y][i])%Mod;
    28     
    29     for(int i=1;i<=sz[x];i++)
    30         for(int j=0;j<=sz[y];j++){
    31             LL a=dp[x][i]*(((fac[sz[y]]-sum[j])%Mod+Mod)%Mod)%Mod;
    32             LL b=c[i+j-1][j]*c[sz[x]+sz[y]-i-j][sz[y]-j]%Mod;
    33             (tmp[i+j]+=a*b%Mod)%=Mod;
    34         }
    35     sz[x]+=sz[y];
    36     for(int i=1;i<=sz[x];i++)
    37         dp[x][i]=tmp[i];    
    38 }
    39 
    40 void DP(int x,int f){
    41     if(fa[x]==f)return;
    42     clr(dp[x]);sz[x]=1;
    43     fa[x]=f;dp[x][1]=1;
    44     for(int i=fir[x];i;i=nxt[i])
    45         if(to[i]!=f){
    46             DP(to[i],x);
    47             Update(x,to[i]);
    48         }
    49 }
    50 
    51 int st[N],top;
    52 void DFS(int x,int f){
    53     st[++top]=x;
    54     for(int i=fir[x];i;i=nxt[i])
    55         if(to[i]!=f)DFS(to[i],x);
    56 }
    57 int T,cas,n,a,b;
    58 void Init(){
    59     clr(fir);clr(fa);
    60     top=ans=cnt=0;
    61 }
    62 
    63 int main(){
    64     Prepare();
    65     scanf("%d",&T);
    66     while(T--){
    67         Init();
    68         scanf("%d",&n);
    69         for(int i=1;i<n;i++){
    70             scanf("%d%d",&a,&b);
    71             addedge(a,b);
    72         }
    73         DFS(1,0);
    74         for(int i=1;i<=n;i++){
    75             DP(st[i],-1);
    76             for(int j=1;j<=n;j++)
    77                 (ans+=dp[st[i]][j])%=Mod;
    78         }
    79         printf("Case #%d: %lld
    ",++cas,ans);
    80     }
    81     return 0;
    82 }
     
  • 相关阅读:
    Java :BufferedWriter类和BufferedReader类的构造方法、主要方法
    多线程:四大线程池详解
    多线程:head first Thread.join()
    多线程: 多线程中断机制
    多线程:深入Thread.sleep
    多线程:线程池原理
    java:java构造器和java方法的区别
    java: Java中this和super的用法总结
    postman: 用于网页调试和发送Http请求的chrome插件
    json:JSONObject包的具体使用(JSONObject-lib包是一个beans,collections,maps,java arrays和xml和JSON互相转换的包)
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5943549.html
Copyright © 2011-2022 走看看