题解:【ABC245F】Endless Walk

题目链接

本题解适合像我这样的不具备思维能力的选手。

首先根据题意,一个点如果符合要求,那它必然在一个点数大于 \(2\) 的强联通分量里,因为如果只有一个点它就哪里都去不了。所以首先先对图进行缩点,顺带记录下每个强连通分量的大小。然后如果一个点它可以走入这个强连通分量里,就也是符合条件的,所以在缩点后的新图上反向建边,遍历一遍看看符合条件的强连通分量可以走到哪些点,最后看哪些被打上标记即可。

\(Code\)

#include<bits/stdc++.h>
#define int long long
using namespace std;

inline int read()
{
    int s=0,w=1; char c=getchar();
    while(!isdigit(c)) {if(c=='-') w=-1; c=getchar();}
    while(isdigit(c)) s=(s<<3)+(s<<1)+(c^48),c=getchar();
    return s*w;
}

namespace LgxTpre
{
    static const int MAX=2000010;
    static const int INF=20070707070707;

    int n,m;
    int x,y;

    struct Graph
    {
        struct edge
        {
            int nex,to;
        }e[MAX<<1];
        int head[MAX],cnt;
        inline void add(int x,int y)
        {
            e[++cnt].nex=head[x];
            head[x]=cnt;
            e[cnt].to=y;
            return;
        }
    }G1,G2;

    int dfn[MAX],low[MAX],tot;
    int stk[MAX],top;
    int sizcol[MAX],col[MAX],num;
    int vis[MAX];
    void tarjan(int now)
    {
        dfn[now]=low[now]=++tot;
        stk[++top]=now;
        vis[now]=1;
        for(int i=G1.head[now];i;i=G1.e[i].nex)
        {
            int to=G1.e[i].to;
            if(!dfn[to]) 
                tarjan(to),
                low[now]=min(low[now],low[to]);
            else    
                if(vis[to])
                    low[now]=min(low[now],dfn[to]);
        }
        if(low[now]==dfn[now])
        {
            vis[now]=0;
            col[now]=++num;
            ++sizcol[num];
            while(stk[top]!=now) col[stk[top]]=num,++sizcol[num],vis[stk[top]]=0,--top;
            --top;
        }
        return;
    }

    int deg[MAX],flag[MAX],ans;
    inline void dfs(int now)
    {
        flag[now]=1;
        for(int i=G2.head[now];i;i=G2.e[i].nex)
        {
            int to=G2.e[i].to;
            if(!flag[to]) dfs(to);
        }
        return;
    }

    inline void lmy_forever()
    {
        n=read(),m=read();
        for(int i=1;i<=m;++i)
            x=read(),y=read(),G1.add(x,y);
        for(int i=1;i<=n;++i)
            if(!dfn[i])
                tarjan(i);
        for(int i=1;i<=n;++i)
            for(int j=G1.head[i],to;j;j=G1.e[j].nex)
                if(col[i]!=col[to=G1.e[j].to])
                    ++deg[i],G2.add(col[to],col[i]);
        for(int i=1;i<=num;++i)
            if(sizcol[i]>=2)
                dfs(i);
        for(int i=1;i<=num;++i)
            if(flag[i])
                ans+=sizcol[i];
        cout<<ans;
    }
};

signed main()
{
    LgxTpre::lmy_forever();
    return (0-0);
}
posted @ 2022-11-14 14:21  LgxTpre  阅读(25)  评论(0编辑  收藏  举报