• [COCI2006-2007 Contest#3] BICIKLI


    不难的一道题,就是码的时候出了点问题,看了其他巨佬的题解才发现问题所在...

    题目大意:

    给定一个有向图,n个点,m条边。请问,1号点到2号点有多少条路径?如果有无限多条,输出inf,如果有限,输出答案模1e9的余数。

    首先是0的情况:

      不存在1~2的路径,即图不一定联通(不这样特判也可以,但是常数会小一点)

    其次是inf的情况:

      如果在1~2的某条路径中存在某个点属于某个强连通分量,那么这条路径就可以在这个强连通分量里无限走下去,答案就是inf

    一般情况:

      如果这条路径不属于第二种情况,那就考虑计数吧...

      我们可以用一个dp数组计数,然后乱搞BFS即可,不用考虑是否vis,因为排除了第二种情况后显然是不会过度访问(RE)的

      同时我们可以记录每一个节点的入度个数,在最后BFS,DP的时候,根据入度可以减少判断很多情况

    同时:一个小问题:在考虑情况2的时候,我们需要建立反向边,以便判断1,2可达性(刚开始想当然了这个没判)

     

     1 #pragma GCC optimize("Ofast")
     2 #pragma GCC optimize(3)
     3 #include<cstdio>
     4 #include<iostream>
     5 #include<cstring>
     6 #include<queue>
     7 #define ha 1000000000
     8 using namespace std;
     9 inline int read(){
    10     int ans=0,f=1;char chr=getchar();
    11     while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
    12     while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
    13     return ans*f;
    14 }void write(int x){
    15     if(x<0) putchar('-'),x=-x;
    16     if(x>9) write(x/10);
    17     putchar(x%10+'0');
    18 }const int M=1e5+5;
    19 int head[M],head1[M],ver1[M],nxt1[M],ver[M],nxt[M],tot,n,m,vis1[M],vis2[M],dfn[M],low[M],ins[M],sta[M],top,t,col,color[M],cnt[M],tot1,dp[M],in[M];
    20 inline void add(int x,int y){ver[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
    21 inline void add1(int x,int y){ver1[++tot1]=y;nxt1[tot1]=head1[x];head1[x]=tot1;}
    22 void dfs1(int x){for(int i=head[x];i;i=nxt[i])if(in[ver[i]]++,!vis1[ver[i]])dfs1(ver[vis1[ver[i]]=1,i]);}
    23 void dfs2(int x){for(int i=head1[x];i;i=nxt1[i])if(!vis2[ver1[i]])dfs2(ver1[vis2[ver1[i]]=1,i]);}
    24 inline bool check_LT(){vis2[2]=1,dfs2(2);if(vis1[vis1[1]=1,dfs1(1),2]) return 0;return 1;}
    25 void Tarjan(int x){
    26     sta[top++]=x;low[x]=dfn[x]=++t;ins[x]=1;
    27     for(register int i=head[x];i;i=nxt[i])
    28         if(ins[ver[i]]==1) low[x]=min(low[x],dfn[ver[i]]);
    29         else if(ins[ver[i]]==0) low[x]=min(low[Tarjan(ver[i]),x],low[ver[i]]);
    30     low[x]==dfn[x]?++col:col;
    31     if(low[x]==dfn[x])do{--top,color[sta[top]]=col,ins[sta[top]]=-1,++cnt[col];}while(sta[top]!=x);
    32 }queue<int> q;
    33 void BFS(){
    34     q.push(1);dp[1]=1;
    35     while(!q.empty()){
    36         int x=q.front();q.pop();
    37         for(register int i=head[x];i;i=nxt[i]){
    38             if(!vis1[ver[i]]) continue;
    39             dp[ver[i]]=(dp[ver[i]]+dp[x])%ha;
    40             if(!--in[ver[i]])    q.push(ver[i]);
    41         }
    42     }
    43 }
    44 int main(){
    45     n=read(),m=read();
    46     for(register int i=1,x,y;i<=m;++i) x=read(),y=read(),add(x,y),add1(y,x);
    47     if(check_LT()){return puts("0"),0;}
    48     for(register int i=1;i<=n;++i) if(!dfn[i]) Tarjan(i);
    49     for(register int i=1;i<=n;++i)
    50         if(vis1[i]&&vis2[i]&&cnt[color[i]]>=2)
    51             return puts("inf"),0;
    52     return BFS(),write(dp[2]),0;
    53 }
  • 相关阅读:
    redis概要学习
    http协议格式详解
    浅谈mysql
    linux常用命令
    Linux 程序管理
    认识与分析日志文件
    认识与学习bash
    例行任务管理
    软件安装的三大方法
    关于一些感慨
  • 原文地址:https://www.cnblogs.com/zhenglw/p/10750962.html
Copyright © 2020-2023  润新知