1 条题解

  • 0
    @ 2025-8-24 22:02:14

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 06ray
    再见了,OI

    搬运于2025-08-24 22:02:14,当前版本为作者最后更新于2018-08-02 17:59:17,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    先膜楼下的chen_zhe大佬%%%

    这题思路不难,可能是道假紫题。

    大体思路如下:

    先判断从1到2点是否有无限条路径。什么时候就会有无限条路径呢?不难想到,当出现一个环且从1节点到2节点能经过它时,就会有无数条路径可走。判断是否有环的方法很简单,只需要求强连通分量(tarjan模板不阐述)。

    求好之后我们还得判断从1节点到2节点是否可以遍历到一个环,可以用一个BFS来模拟。我们先用BFS求出从1号节点出发能遍历到的所有的点。然后我们建一个反向的图,再用BFS求出在反向图中从2号点出发能遍历到的所有的点。接着判断如果某一个点既可以被2遍历到又能被1遍历到并且它在一个环之内,就说明有无限条路径,输出inf。

    最后,我们在用一个BFS求出从1号点到2号点的路径总数即可。

    下面有请可爱丑陋的代码酱出场qwq

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=101000;
    struct edge{
        int to,cost;
    };
    stack<int> s;
    int n,m,dfn[MAXN],low[MAXN],color[MAXN],vis[MAXN],used[MAXN],a[MAXN],countt[MAXN],in[MAXN];
    int colornum; 
    vector<int> G[MAXN];
    vector<int> rG[MAXN];
    inline int read()//读入优化
    {
        int num=0;
        char ch=getchar();
        while(ch>'9'||ch<'0') ch=getchar();
        while(ch>='0'&&ch<='9')
         {
             num=num*10+ch-'0';
             ch=getchar();
         }
        return num; 
    }
    int cnt;
    void tarjan(int u)//Tarjan模板,求出强连通分量
    {
        cnt++;
        dfn[u]=low[u]=cnt;
        used[u]=true;
        s.push(u);
        vis[u]=true;
        for(int i=0; i<G[u].size(); i++)
        {
            int v=G[u][i];
            if(!dfn[v])
            {
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else
            {
                if(vis[v])
                {
                    low[u]=min(low[u],dfn[v]);
                }
            }
        }
        if(dfn[u]==low[u])
        {
            colornum++;
            while(s.top()!=u)
            {
                int t=s.top();
                s.pop();
                color[t]=colornum;
                vis[t]=false;
            }
            s.pop();
            color[u]=colornum;
            vis[u]=false;
        }
    }
    void bfs1(int x)//求出从1号节点出发能遍历到的所有的点
    {
        memset(used,0,sizeof(used));
        queue<int>q;
        q.push(x);
        used[x]=true;
        while(!q.empty())
        {
            int v=q.front();
            q.pop();
            for(int i=0; i<G[v].size(); i++)
            {
                if(!used[G[v][i]])
                {
                    used[G[v][i]]=true;//判断是否能被1遍历到
                    q.push(G[v][i]);
                }
                in[G[v][i]]++;
            }
        }
    }
    void bfs2(int x)//求出在逆向图中从2号节点出发能遍历到的所有的点
    {
        memset(vis,0,sizeof(vis));
        queue<int>q;
        q.push(x);
        vis[x]=true;
        while(!q.empty())
        {
            int v=q.front();
            q.pop();
            for(int i=0; i<rG[v].size(); i++)
            {
                if(!vis[rG[v][i]])
                {
                    vis[rG[v][i]]=true;//判断是否能被2遍历到
                    q.push(rG[v][i]);
                }
            }
        }
    }
    void bfs3(int x)
    {
        queue<int>q;
        q.push(x);
        countt[x]=1;
        while(!q.empty())
        {
            int v=q.front();
            q.pop();
            for(int i=0; i<G[v].size(); i++)
            {
                if(vis[G[v][i]])
                {
                    countt[G[v][i]]+=countt[v];
                    countt[G[v][i]]%=1000000000;//取模
                    if(!--in[G[v][i]]) q.push(G[v][i]);//小优化
                }
            }
        }
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1; i<=m; i++)
        {
            int x,y;
            x=read(),y=read();
            G[x].push_back(y);//邻接表存储
            rG[y].push_back(x);//建反向图
        }
        for(int i=1; i<=n; i++)
        if(!dfn[i]) tarjan(i);
        bfs1(1);
        bfs2(2);
        for(int i=1; i<=n; i++)
        a[color[i]]++;//统计每个强连通分中节点个数
        for(int i=1; i<=n; i++)
        if(used[i]&&vis[i]&&a[color[i]]!=1)//可以被2遍历到又能被1遍历到并且在一个环之内
        {
            cout<<"inf";
            return 0;
        }
        bfs3(1);
        cout<<countt[2];
        return 0;
    }
    

    管理大大求过

    • 1

    信息

    ID
    3656
    时间
    1000ms
    内存
    128MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者