转化补集的思想,首先求出任意两点之间路径数目
然后求两条路径第一次相交在点k(按照拓扑排序的顺序)的数目,显然这里要用到容斥
然后pascal有坑爹的范围检测,所以运算中有些不会影响到答案但会爆int64的地方要判断一下
1 const inf=1e18; 2 var w:array[0..200,0..200] of boolean; 3 f:array[0..200,0..200] of int64; 4 g:array[0..200] of int64; 5 q,rd:array[0..200] of longint; 6 a,b,c,d,n,m,x,y,i,j,k,h,t:longint; 7 ans:int64; 8 9 begin 10 readln(n,m); 11 for i:=1 to m do 12 begin 13 readln(x,y); 14 w[x,y]:=true; 15 inc(rd[y]); 16 end; 17 for i:=1 to n do 18 if rd[i]=0 then 19 begin 20 inc(t); 21 q[t]:=i; 22 end; 23 h:=1; 24 while h<=t do 25 begin 26 x:=q[h]; 27 for i:=1 to n do 28 if w[x,i] then 29 begin 30 dec(rd[i]); 31 if rd[i]=0 then 32 begin 33 inc(t); 34 q[t]:=i; 35 end; 36 end; 37 38 inc(h); 39 end; 40 readln(a,b,c,d); 41 for i:=1 to n do 42 for j:=i to n do 43 if q[i]=q[j] then f[q[i],q[j]]:=1 44 else begin 45 for k:=i to j-1 do 46 if w[q[k],q[j]] then 47 if f[q[i],q[j]]+f[q[i],q[k]]<inf then f[q[i],q[j]]:=f[q[i],q[j]]+f[q[i],q[k]]; 48 end; 49 50 for i:=1 to n do 51 begin 52 if (f[q[i],b]<>0) and (f[q[i],d]<>0) then 53 begin 54 g[q[i]]:=f[a,q[i]]*f[c,q[i]]; 55 for j:=1 to i-1 do 56 g[q[i]]:=g[q[i]]-g[q[j]]*f[q[j],q[i]]*f[q[j],q[i]]; 57 end; 58 end; 59 for i:=1 to n do 60 ans:=ans-g[i]*f[i,b]*f[i,d]; 61 ans:=ans+f[a,b]*f[c,d]; 62 writeln(ans); 63 end.