f[i][j]表示i、j的亲缘关系。
f[i][j]=(f[i][fa[j]]+f[i][mo[j]])/2或f[i][j]=(f[fa[i]][j]+f[mo[i]][j])/2
按拓扑序推一遍就好了。
听说有高精度小数。
整天邻接表不开两倍内存,还调半天调不出,跟个傻逼一样。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define sqr(x) ((x)*(x))
#define G getchar()
#define LL long long
#define pll pair<LL,LL>
#define mkp make_pair
#define X first
#define Y second
#define N 305
int n,m,fa[N],mo[N];
int he[N],ne[N<<1],to[N<<1],tot;
int q[N],in[N];
struct DATA{short dat[N];int ln;}f[N][N];
DATA operator +(DATA x,DATA y){
x.ln=max(x.ln,y.ln);
int i;per(i,x.ln,1)
if((x.dat[i]+=y.dat[i])>9)++x.dat[i-1],x.dat[i]-=10;
x.dat[0]+=y.dat[0];
while(x.ln&&!x.dat[x.ln])--x.ln;
return x;
}
DATA div2(DATA x){
int i;
rep(i,0,x.ln){
if(x.dat[i]&1)x.dat[i+1]+=10;
x.dat[i]>>=1;
}
if(x.dat[x.ln+1])x.dat[++x.ln]=5;
return x;
}
void add(int x,int y){
to[++tot]=y;ne[tot]=he[x];he[x]=tot;
}
int read(){
int x=0;char ch=G;
while(ch<48||ch>57)ch=G;
for(;ch>47&&ch<58;ch=G)x=x*10+ch-48;
return x;
}
void BFS(){
int Ft=1,Rr=1,u,v,i;
rep(i,1,n){
if(!in[i])q[Rr++]=i;f[i][i].dat[0]=1;
}
while(Ft<Rr){
u=q[Ft++];
per(i,Ft-2,1){
v=q[i];f[u][v]=f[v][u]=div2(f[v][fa[u]]+f[v][mo[u]]);
}
for(i=he[u];i;i=ne[i])if(--in[v=to[i]]==0)q[Rr++]=v;
}
}
void write(DATA x){
printf("%d",x.dat[0]*100+x.dat[1]*10+x.dat[2]);int i;
if(x.ln>2){
putchar('.');
rep(i,3,x.ln)printf("%d",x.dat[i]);
}
puts("%");
}
int main(){
int i,x,Q,y;
n=read();m=read();
while(m--){
in[x=read()]=2;fa[x]=read();mo[x]=read();
add(fa[x],x);add(mo[x],x);
}
BFS();
for(Q=read();Q--;){
x=read();y=read();write(f[x][y]);
}
return 0;
}