Evanyou Blog 彩带

  题目传送门

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: 
3
输入样例#2: 
6 8
1 3
1 4
3 2
4 2
5 6
6 5
3 4
4 3
输出样例#2: 
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;
}
原文地址:https://www.cnblogs.com/cytus/p/9838870.html