bzoj1471

转化补集的思想,首先求出任意两点之间路径数目

然后求两条路径第一次相交在点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.
View Code
原文地址:https://www.cnblogs.com/phile/p/4489863.html