题目描述:
竹林可以看作是一个n 个点的树,每个边有一个边长i w ,其中有k 个关键点,永琳需
要破坏这些关键点才能走出竹林迷径。
然而永琳打算将这k 个点编号记录下来,然后随机排列,按这个随机的顺序走过k 个点,
但是两点之间她只走最短路线。初始时永琳会施展一次魔法,将自己传送到选定的k 个点中
随机后的第一个点。
现在永琳想知道,她走过路程的期望是多少,答案对998244353 取模。
注意,如果对期望不理解,题目最后有详细解释,请自行阅读。
输入:
第一行一个数Case,表示测试点编号。(样例的编号表示其满足第Case 个测试点的性
质)
下一行一个n,表示树的点数。
下面n-1 行,每行三个数i i i u,v,w ,表示一条边连接i i i u 和v,长度为w 。
下面一行一个数k,表示关键点数。
下面一行k 个数,表示k 个关键点的编号。
输出:
一行一个数,表示答案(对998244353 取模)。
数据范围:
对于100%的数据,保证 1≤ w ≤10 ,1≤N≤1e6,1≤K≤1e6
算法标签:DFS???概率期望
思路:
考虑对于每一条边对于答案会造成的贡献,当存在某两个选中的点在边的两边即存在情况使这条边出现次数++,根据这个思路退式子即可。
考差的不走心题解,式子都不给了
以下代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define il inline #define LL long long #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=1e6+5,p=998244353; int n,head[N],ne[N<<1],to[N<<1],v[N<<1],cnt,k,w[N],s[N];LL ans,base; il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;} il void insert(int x,int y,int z){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;v[cnt]=z;} il LL ksm(LL a,int y){LL b=1;while(y){if(y&1)b=b*a%p;a=a*a%p;y>>=1;}return b;} void dfs(int x,int fa){ if(w[x])s[x]++; for(int i=head[x];i;i=ne[i]){ if(fa==to[i])continue; dfs(to[i],x);s[x]+=s[to[i]]; ans=(ans+(LL)s[to[i]]*(LL)(k-s[to[i]])%p*(LL)v[i]%p)%p; } } int main() { //freopen("path.in","r",stdin); //freopen("path.in","w",stdout); read();n=read();for(int i=1;i<n;i++){int x=read(),y=read(),z=read();insert(x,y,z);insert(y,x,z);} k=read();for(int i=1;i<=k;i++)w[read()]=1; cnt=0;dfs(1,0); base=2ll*(LL)ksm((LL)k,p-2)%p; printf("%lld ",ans*base%p); return 0; }