Description
梦游中的你来到了一棵 N 个节点的树上. 你一共做了 Q 个梦, 每个梦需要你从点 u 走到 点 v 之后才能苏醒, 由于你正在梦游, 所以每到一个节点后,你会在它连出去的边中等概率地 选择一条走过去, 为了确保第二天能够准时到校, 你要求出每个梦期望经过多少条边才能苏 醒. 为了避免精度误差, 你要输出答案模10^9 + 7的结果.
对于 20%的数据, N <= 10.
对于 40%的数据, N <= 1000.
另有 20%的数据, 保证给定的树是一条链.
对于 100%的数据, N <= 100000, Q <= 100000.
Solution
树形dp,同这个
然后求个lca算一下就行了
Code
#include <stdio.h>
#include <string.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int N=200005;
const int E=400005;
struct edge {int y,w,next;} e[E];
int ls[N],hate[N],edCnt;
int rc[500][500];
bool vis[N];
long long ans;
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void add_edge(int x,int y,int w) {
e[++edCnt]=(edge) {y,w,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {x,w,ls[y]}; ls[y]=edCnt;
}
void dfs2(int now,int fa,int sum) {
if (vis[hate[now]]) return ;
ans+=sum;
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y==fa) continue;
vis[e[i].y]=1;
dfs2(e[i].y,now,rc[sum][e[i].w]);
vis[e[i].y]=0;
}
}
void dfs1(int now,int fa) {
vis[now]=1; //st=now;
dfs2(now,0,0);
vis[now]=0;
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y==fa) continue;
dfs1(e[i].y,now);
}
}
int main(void) {
freopen("xor.in","r",stdin);
freopen("xor.out","w",stdout);
char ch=getchar();
int k=read();
rep(i,0,k-1) rep(j,0,k-1) rc[i][j]=read();
int n=read();
rep(i,2,n) {
int x=read(),y=read(),w=read();
add_edge(x,y,w);
}
rep(i,1,n) hate[i]=read();
dfs1(1,0);
printf("%lld\n", ans);
return 0;
}