BICIKLI
题意翻译
给定一个有向图,n个点,m条边。请问,1号点到2号点有多少条路径?如果有无限多条,输出inf,如果有限,输出答案模10^9的余数。
两点之间可能有重边,需要看成是不同的路径。
题目描述
A bicycle race is being organized in a land far, far away. There are N town in the land, numbered 1 through N. There are also M one-way roads between the towns. The race will start in town 1 and end in town 2. How many different ways can the route be set? Two routes are considered different if they do not use the exact same roads.
输入输出格式
输入格式:
The first line of input contains two integers N and M (1 ≤ N ≤ 10 000, 1 ≤ M ≤ 100 000), the number of towns and roads. Each of the next M lines contains two different integers A and B, representing a road between towns A and B. Towns may be connected by more than one road.
输出格式:
Output the number of distinct routes that can be set on a single line. If that number has more than nine digits, output only the last nine digits of the number. If there are infinitely many routes, output "inf".
输入输出样例
说明
本题数据已经被更改,无需保留前导0
分析:
考试的题,考场上居然没想到用$Tarjan$来处理环,傻逼的打了几个$DFS$,然后开心的$WA$成狗。
首先不难想到$inf$的情况就是$1$到$2$的任一路径上有环出现,那么我们可以这么处理:先正反向建边,然后分别以$1,2$为起点$DFS$,然后标记那些点是$1$到$2$的路径上的点,再就可以缩点重建图,如果发现某个强联通分量既是路径上的点而且大小又超过$1$那么就是$inf$,否则就跑拓扑排序记录路径数就行了。
Code:
//It is made by HolseLee on 23rd Oct 2018 //Luogu.org P4645 #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define mod (1000000000) using namespace std; const int N=1e5+7; int n,m,head[N],cnte,siz[N],cnt1,cnt2,dg[N]; int dfn[N],low[N],scc[N],idx,tot,sta[N],top,ans[N]; int h1[N],to1[N],nxt1[N],h2[N],to2[N],nxt2[N]; bool vis1[N],vis2[N],ins[N]; struct Edge { int u,v,to,nxt; }e[N],edge[N]; queue<int>q; inline int read() { char ch=getchar(); int num=0; bool flag=false; while( ch<'0' || ch>'9' ) { if( ch=='-' ) flag=true; ch=getchar(); } while( ch>='0' && ch<='9' ) { num=num*10+ch-'0'; ch=getchar(); } return flag ? -num : num; } inline void add(int x,int y) { to1[++cnt1]=y, nxt1[cnt1]=h1[x], h1[x]=cnt1; to2[++cnt2]=x, nxt2[cnt2]=h2[y], h2[y]=cnt2; } inline void add_edge(int x,int y) { e[++cnte].to=y; e[cnte].nxt=head[x]; head[x]=cnte; } void dfs(int x,bool *vis,int *h,int *to,int *nxt) { vis[x]=1; for(int i=h[x],y; i; i=nxt[i]) { y=to[i]; if( !vis[y] ) dfs(y,vis,h,to,nxt); } } void tarjan(int x) { dfn[x]=low[x]=++idx; ins[x]=1; sta[++top]=x; int y; for(int i=head[x]; i; i=e[i].nxt) { y=e[i].to; if( !dfn[y] ) { tarjan(y); low[x]=min(low[x],low[y]); } else if( ins[y] ) { low[x]=min(low[x],dfn[y]); } } if( dfn[x]==low[x] ) { tot++; do{ y=sta[top--]; ins[y]=0; scc[y]=tot; siz[tot]++; }while(y!=x); } } int main() { freopen("bicikli.in","r",stdin); freopen("bicikli.out","w",stdout); n=read(), m=read(); for(int i=1; i<=m; ++i) edge[i].u=read(), edge[i].v=read(), add(edge[i].u,edge[i].v); dfs(1,vis1,h1,to1,nxt1); dfs(2,vis2,h2,to2,nxt2); if( !vis1[2] ) puts("0"), exit(0); for(int i=1; i<=m; ++i) { if( vis1[edge[i].u] && vis1[edge[i].v] ) add_edge(edge[i].u,edge[i].v), dg[edge[i].v]++; } for(int i=1; i<=n; ++i) if( !dfn[i] && vis1[i] ) tarjan(i); if( scc[1]==scc[2] ) puts("inf"), exit(0); for(int i=1; i<=n; ++i) if( siz[scc[i]]>1 && vis1[i] && vis2[i] ) puts("inf"), exit(0); q.push(1);ans[1]=1; int x,y; while( !q.empty() ) { x=q.front(); q.pop(); for(int i=head[x]; i; i=e[i].nxt) { y=e[i].to; ans[y]=(ans[y]+ans[x])%mod; if( !(--dg[y]) ) q.push(y); } } printf("%d ",ans[2]); return 0; }