CF802L Send the Fool Further! (hard) 树上高斯消元
朴素的高斯消元是 $O(n^3)$ 的,但是由于叶节点是终止节点,所以可以逐层向上推成 $k\times f(fa)+b$ 的形式.
推到根节点时直接取根节点的 $b$ 值就可以了.
code:
#include <cstdio> #include <cstring> #include <algorithm> #define ll long long #define mod 1000000007 #define N 100067 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int qpow(int x,int y) { int tmp=1; for(;y;y>>=1,x=(ll)x*x%mod) if(y&1) tmp=(ll)tmp*x%mod; return tmp; } int n,edges; int deg[N],hd[N],to[N<<1],nex[N<<1],val[N<<1],k[N],b[N]; void add(int u,int v,int c) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c; } void dfs(int x,int ff,int pr) { // deg[x]=1; for(int i=hd[x];i;i=nex[i]) if(to[i]!=ff) dfs(to[i],x,val[i]); // ,++deg[x]; if(deg[x]==1) k[x]=0,b[x]=0; else { int len=0; int bb=0; int kk=0; for(int i=hd[x];i;i=nex[i]) if(to[i]!=ff) (kk+=k[to[i]])%=mod; for(int i=hd[x];i;i=nex[i]) len+=val[i]; for(int i=hd[x];i;i=nex[i]) if(to[i]!=ff) (bb+=b[to[i]])%=mod; int t=(ll)qpow((deg[x]-kk+mod)%mod,mod-2); b[x]=(ll)(bb+len)*t%mod; k[x]=t; } } int main() { // setIO("input"); scanf("%d",&n); int i,j; for(i=1;i<n;++i) { int x,y,z; scanf("%d%d%d",&x,&y,&z),++x,++y; ++deg[x],++deg[y]; add(x,y,z),add(y,x,z); } dfs(1,0,0); printf("%d\n",(ll)b[1]%mod); return 0; }