P4645 [COCI2006-2007 Contest#3] 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".
输入输出样例
6 7
1 3
1 4
3 2
4 2
5 6
6 5
3 4
6 8
1 3
1 4
3 2
4 2
5 6
6 5
3 4
4 3
3
inf
说明
本题数据已经被更改,无需保留前导0
Solution:
本题Tarjan缩点+拓扑序dp。
考虑结果为inf的情况,只要1经过一个环再到2就说明有无数条路径。
于是我们建两幅图,一正一反,分别处理出1能到达的所有点和能到达2的所有点,然后再对原图缩点(小优化是只需要对1能访问的点缩点就好了),枚举每个点作为中间点,判断1能否经过该点到达2且该点在一个环上,若满足条件说明解为inf咯。
判完inf的情况,说明剩下的图是个DAG了,直接拓扑序dp就好了(注意模数是$1e9$,开始下意识当作$1e9+7$,然后WA了,咕咕咕~)。
代码:
/*Code by 520 -- 9.5*/ #include<bits/stdc++.h> #define il inline #define ll long long #define RE register #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++) #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--) using namespace std; const int N=200005,mod=1e9; int n,m,rd[N],bl[N],scc,low[N],dfn[N],siz[N],tot; int to[N],net[N],h[N],cnt,stk[N],top,ans[N]; int To[N],Net[N],H[N]; bool vis1[N],vis2[N],ins[N]; struct node{ int u,v; }e[N]; int gi(){ int a=0;char x=getchar(); while(x<'0'||x>'9')x=getchar(); while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+(x^48),x=getchar(); return a; } il void add(int u,int v){ to[++cnt]=v,net[cnt]=h[u],h[u]=cnt; To[++cnt]=u,Net[cnt]=H[v],H[v]=cnt; } void dfs(int u,bool *vis,int *h,int *to){ vis[u]=1; for(RE int i=h[u];i;i=net[i]) if(!vis[to[i]]) dfs(to[i],vis,h,to); } void tarjan(int u){ dfn[u]=low[u]=++tot,stk[++top]=u,ins[u]=1; for(RE int i=h[u];i;i=net[i]) if(!dfn[to[i]]) tarjan(to[i]),low[u]=min(low[u],low[to[i]]); else if(ins[to[i]]) low[u]=min(low[u],dfn[to[i]]); if(dfn[u]==low[u]){ ++scc; while(stk[top+1]!=u) bl[stk[top]]=scc,ins[stk[top--]]=0,siz[scc]++; } } queue<int>q; int main(){ n=gi(),m=gi(); For(i,1,m) e[i].u=gi(),e[i].v=gi(),add(e[i].u,e[i].v); dfs(1,vis1,h,to),dfs(2,vis2,H,To); if(!vis1[2]) cout<<0,exit(0); memset(h,0,sizeof(h)),cnt=0; For(i,1,m) if(vis1[e[i].u]&&vis1[e[i].v]) add(e[i].u,e[i].v),rd[e[i].v]++; For(i,1,n) if(!dfn[i]&&vis1[i]) tarjan(i); if(bl[1]==bl[2]) cout<<"inf",exit(0); For(i,1,n) if(vis1[i]&&vis2[i]&&siz[bl[i]]>1) cout<<"inf",exit(0); q.push(1),ans[1]=1; while(!q.empty()){ RE int u=q.front();q.pop(); for(RE int i=h[u];i;i=net[i]){ ans[to[i]]=(ans[to[i]]+ans[u])%mod; if(!--rd[to[i]])q.push(to[i]); } } cout<<ans[2]; return 0; }