ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

K-Set Tree (树的节点贡献+组合数+减法思维)(codeforce 795)

2022-06-05 12:04:12  阅读:227  来源: 互联网

标签:795 ch int tree Tree vertices long Set size


F. K-Set Tree
time limit per test3 seconds
memory limit per test512 megabytes
inputstandard input
outputstandard output
You are given a tree G with n vertices and an integer k. The vertices of the tree are numbered from 1 to n.

For a vertex r and a subset S of vertices of G, such that |S|=k, we define f(r,S) as the size of the smallest rooted subtree containing all vertices in S when the tree is rooted at r. A set of vertices T is called a rooted subtree, if all the vertices in T are connected, and for each vertex in T, all its descendants belong to T.

You need to calculate the sum of f(r,S) over all possible distinct combinations of vertices r and subsets S, where |S|=k. Formally, compute the following:
∑r∈V∑S⊆V,|S|=kf(r,S),
where V is the set of vertices in G.

Output the answer modulo 109+7.

Input
The first line contains two integers n and k (3≤n≤2⋅105, 1≤k≤n).

Each of the following n−1 lines contains two integers x and y (1≤x,y≤n), denoting an edge between vertex x and y.

It is guaranteed that the given edges form a tree.

Output
Print the answer modulo 109+7.

Examples
inputCopy
3 2
1 2
1 3
outputCopy
25
inputCopy
7 2
1 2
2 3
2 4
1 5
4 6
4 7
outputCopy
849
Note
The tree in the second example is given below:


We have 21 subsets of size 2 in the given tree. Hence,
S∈{{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{2,3},{2,4},{2,5},{2,6},{2,7},{3,4},{3,5},{3,6},{3,7},{4,5},{4,6},{4,7},{5,6},{5,7},{6,7}}.
And since we have 7 vertices, 1≤r≤7. We need to find the sum of f(r,S) over all possible pairs of r and S.

Below we have listed the value of f(r,S) for some combinations of r and S.

r=1, S={3,7}. The value of f(r,S) is 5 and the corresponding subtree is {2,3,4,6,7}.
r=1, S={5,4}. The value of f(r,S) is 7 and the corresponding subtree is {1,2,3,4,5,6,7}.
r=1, S={4,6}. The value of f(r,S) is 3 and the corresponding subtree is {4,6,7}.
View problem

思路:

  • 这是一道算节点贡献的题
  • 贡献可以分为2中情况 为 根,和不为根, 但是这个点代表的2种贡献,都是以这个点为最近的公共祖先(最小的子节点)
  • 2种情况 都是 分别从他的儿子树们,选一些节点出来, 不能所有点都选一个儿子的,这样就不能保证最近公共祖先
  • 那么怎么办内?,就利用减法思维 C(sz,K)   -   C(各个儿子的size,K,), 这样就一定能保证上面的条件,
  • 根 就 上面的 xN;
  • 不是根,就枚举 相邻的节点,把他根, 然后 种类数X剩下的szX父亲的数量
  • 种类数: 同理可得 C(sz,K)   -   C(各个儿子的size,K,),当然这里用 减法 优化时间复杂度,不然就n^2了;
  • 先把 C(各个相邻节点的size,K,) 求和, 然后 这个和 - C(父亲size,K)
  • 具体看代码(很简单)

核心:就是 组合数减法,可以让最小公共祖先成立

#include <bits/stdc++.h>
using namespace std;
#define ri register int 
#define M  200005

template <class G> void read(G &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=f?-x:x;
    return ;
} 
long long ans=0;
const int mod=1e9+7;
long long  n,m;
vector<int> p[M];
int vis[M];
int sz[M];
long long inv[M],arr[M];
long long qsn(long long a,int n)
{
    long long ans=1;
    while(n)
    {
        if(n&1) ans=ans*a%mod;
        n>>=1;a=a*a%mod;
    }
    return ans;
}
long long zh(long long a,long long b)
{
    if(a==b||b==0) return 1;
    if(a<b||a==0) return 0;
    return arr[a]*inv[a-b]%mod*inv[b]%mod;
}
void init(){
    
    arr[0]=1;inv[0]=1;
    for(ri i=1;i<=n;i++)
    {
        arr[i]=i*arr[i-1]%mod;
        inv[i]=qsn(arr[i],mod-2);
    }
    
}
void dfs1(int a)
{
    vis[a]=1;
    sz[a]++;
    for(ri i=0;i<p[a].size();i++)
    {
        int b=p[a][i];
        if(vis[b]) continue;
        dfs1(b);
        sz[a]+=sz[b];
    }
    return ;
}


void dfs2(int a)
{
    vis[a]=1;
    ans=(ans+zh(n,m)*n%mod)%mod; // geng
    long long tmp=0;
    for(ri i=0;i<p[a].size();i++)
    {
        int b=p[a][i];
        if(vis[b]==0)
        {
            ans=(ans-zh(sz[b],m)*n%mod+mod)%mod;
            tmp=(tmp+zh(sz[b],m))%mod;
        }
        else
        {
            ans=(ans-zh(n-sz[a],m)*n%mod+mod)%mod;
            tmp=(tmp+zh(n-sz[a],m))%mod;
        }
    }
    for(ri i=0;i<p[a].size();i++)
    {
        int b=p[a][i];
        if(vis[b]==0)
        {
            ans=(ans+zh(n-sz[b],m)*(n-sz[b])%mod*sz[b])%mod;
            ans=(ans-(tmp-zh(sz[b],m))*(n-sz[b])%mod*sz[b]%mod+mod)%mod;
        }
        else
        {
            ans=(ans+zh(sz[a],m)*(sz[a])%mod*(n-sz[a]))%mod;
            ans=(ans-(tmp-zh(n-sz[a],m))*(sz[a])%mod*(n-sz[a])%mod+mod)%mod;
        }
    }
    for(ri i=0;i<p[a].size();i++)
    {
        int b=p[a][i];
        if(vis[b]) continue;
        dfs2(b);
    }
    
    return ;
    
}
int main(){
    
    read(n);
    read(m);
    for(ri i=1;i<n;i++)
    {
        int a,b;
        read(a);read(b);
        p[a].push_back(b);
        p[b].push_back(a);
    }
    init();
    dfs1(1);
    memset(vis,0,sizeof(vis));
    dfs2(1);
    printf("%lld",ans);
    return 0;
    
    
}
View Code

 

标签:795,ch,int,tree,Tree,vertices,long,Set,size
来源: https://www.cnblogs.com/Lamboofhome/p/16343653.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有