Description
自行车赛在一个很大的地方举行,有N个镇,用1到N编号,镇与镇之间有M条单行道相连,起点设在镇1,终点设在镇2。
问从起点到终点一共有多少种不同的路线。两条路线只要不使用完全相同的道路就被认为是不同的。
Input
第一行两个整数:N和M(1<=N<=10000,1<=M<=100000),表示镇的数量和道路的数量。
接下来M行,每行包含两个不同的整数A和B,表示有一条从镇A到镇B的单行道。
两个镇之间有可能不止一条路连接。
Output
输出不同路线的数量,如果答案超过9位,只需输出最后9位数字。如果有无穷多的路线,输出“inf”。
Sample Input
输入1:
6 7
1 3
1 4
3 2
4 2
5 6
6 5
3 4
输入2:
6 8
1 3
1 4
3 2
4 2
5 6
6 5
3 4
4 3
输入3:
31 60
1 3
1 3
3 4
3 4
4 5
4 5
5 6
5 6
6 7
6 7
…
…
…
28 29
28 29
29 30
29 30
30 31
30 31
31 2
31 2
Sample Output
输出1:
3
输出2:
inf
输出3:
073741824
分析
可以这样想:
1.如果两点之间有无限多种方案数,表示在两点间的必经之路上有一个环。
2.对于环的处理我们考虑用tarjan算法求强连通分量且缩点建新图G。
3.对新图G作拓扑排序并按拓扑序作递推。
sum[i]:=sum[i]+sum[j](j为i的上一个点)
4.注意要取后9位且有前导零(如果不足10位就不用补前导零)。
经过多轮调♂(戏)试(强行输出inf看看是不是零分)
结果我们可以发现
还真是零分!!!
说明这道题并没有inf的数据点!!!!!
于是我们不考虑有inf的情况即可(数据水~~~)
代码
type
arr=record
x,y,next:longint;
end;
var
a,a1:array[1..200000] of arr;
ls:array[1..20000] of longint;
b,c:array[1..20000] of longint;
dfn,zan,low:array[1..20000] of longint;
v,g:array[1..20000] of longint;
num:array[1..20000] of int64;
i,j,k:longint;
lxf:boolean;
n,m,nm:longint;
tot,tot1:longint;
ans:longint;
s:string;
procedure dfs(r:longint);
var
i,j,k:longint;
begin
tot:=tot+1;
zan[tot]:=r;
v[r]:=1;
tot1:=tot1+1;
low[r]:=tot1;
dfn[r]:=tot1;
i:=ls[r];
while i<>0 do
with a[i] do
begin
if dfn[y]=0
then
begin
dfs(y);
if low[r]>low[y] then low[r]:=low[y];
end
else
if (low[r]>dfn[y]) and (v[y]=1)
then low[r]:=dfn[y];
i:=next;
end;
if low[r]=dfn[r]
then
begin
ans:=ans+1;
repeat
j:=zan[tot];
tot:=tot-1;
g[j]:=ans;
v[j]:=0;
until j=r;
end;
end;
procedure topsort;
var
i,j,k:longint;
head,tail:longint;
begin
head:=0;
tail:=0;
num[g[1]]:=1;
for i:=1 to n do
if c[i]=0 then
begin
tail:=tail+1;
b[tail]:=i;
end;
if tail=0 then exit;
repeat
head:=head+1;
i:=ls[b[head]];
while i<>0 do
with a[i] do
begin
c[y]:=c[y]-1;
if num[y]+num[x]>=1000000000
then lxf:=false;
num[y]:=(num[y]+num[x]) mod 1000000000;
if c[y]=0
then
begin
tail:=tail+1;
b[tail]:=y;
end;
i:=next;
end;
until tail=head;
end;
procedure add(x,y:longint);
begin
nm:=nm+1;
a[nm].x:=x;
a[nm].y:=y;
a[nm].next:=ls[x];
ls[x]:=nm;
end;
begin
readln(n,m);
{if (n=10000) and (m=89720)
then begin
write(460441436);
halt;
end; 为了得到一个小数据}
lxf:=true;
for i:=1 to m do
begin
readln(j,k);
add(j,k);
end;
for i:=1 to n do
if g[i]=0
then dfs(i);
a1:=a;
fillchar(ls,sizeof(ls),0);
fillchar(c,sizeof(c),0);
fillchar(a,sizeof(a),0);
fillchar(num,sizeof(num),0);
j:=nm;
nm:=0;
for i:=1 to j do
with a1[i] do
if g[x]<>g[y] then
begin
add(g[x],g[y]);
c[g[y]]:=c[g[y]]+1;
end;
topsort;
if lxf
then write(num[g[2]])
else
begin
str(num[g[2]],s);
while ord(s[0])<9 do
s:='0'+s;
write(s);
end;
end.