正题
题目链接:https://www.luogu.org/problemnew/show/P5007
题目大意
一棵树每个点有点权(若T=0T=0T=0点权为1,若T=1T=1T=1点权为该点的编号)。求所有不包含祖先关系的集合的点权之和的和。
解题思路
设fif_ifi表示iii的子树的集合点权之和,gig_igi表示iii的子树的集合个数。
然后有
fx=fx∗gy+fy∗gx+fx+fyf_x=f_x*g_y+f_y*g_x+f_x+f_yfx=fx∗gy+fy∗gx+fx+fy
gx=gx∗gy+gx+gyg_x=g_x*g_y+g_x+g_ygx=gx∗gy+gx+gy
(xxx是yyy的父节点)
然后我们要计算入xxx这个点让fx=fx+wxf_x=f_x+w_xfx=fx+wx,gx=gx+1g_x=g_x+1gx=gx+1
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1001000,XJQ=1e8+7;
ll n,T,tot,g[N],f[N],ls[N];
struct node{ll to,next;
}a[N*2];
void addl(ll x,ll y)
{a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;
}
void dfs(ll x,ll fa)
{for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(y==fa) continue;dfs(y,x);f[x]=(f[x]*g[y]+f[y]*g[x]+f[x]+f[y])%XJQ;g[x]=(g[x]*g[y]+g[x]+g[y])%XJQ;}f[x]=(f[x]+1+T*(x-1))%XJQ;g[x]++;
}
int main()
{scanf("%lld%lld",&n,&T);for(ll i=1;i<n;i++){ll x,y;scanf("%lld%lld",&x,&y);addl(x,y);addl(y,x);}dfs(1,0);printf("%lld",f[1]);
}