1. 程式人生 > >P4645 [COCI2006-2007 Contest#3] BICIKLI

P4645 [COCI2006-2007 Contest#3] BICIKLI

git 題目 有向圖 ads $1 can same 滿足 數據

題意翻譯

給定一個有向圖,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