• 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;
    }    
  • 相关阅读:
    4.数据库表相关操作
    2.快速创建springboot项目 连pom文件里面的配置都不用配了
    1.开始Springboot 基本配置和helloworld
    mysql 对数据库操作的常用sql语句
    mysql简单操作
    1.开始Spring
    关于java中的异常
    关于maven
    npm相关知识点
    git源代码管理工具操作步骤
  • 原文地址:https://www.cnblogs.com/five20/p/9595237.html
Copyright © 2020-2023  润新知