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".
輸入輸出樣例
輸入樣例#1:6 7
1 3
1 4
3 2
4 2
5 6
6 5
3 4
輸出樣例#1:
6 8 1 3 1 4 3 2 4 2 5 6 6 5 3 4 4 3輸入樣例#2:
3
輸出樣例#2:
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; }
P4645 [COCI2006-2007 Contest#3] BICIKLI