1 条题解

  • 0
    @ 2025-4-6 22:04:10

    题意 给出一个有向图,求图的一个子集。

    这个子集中的所有点都是汇点(u是图中的一个顶点,对于图中的每一个顶点v,如果u可以到达v,那么v也可以到达u)。

    思路 一个强联通分量可以保证任意点互相可以到达。但是不一定满足题意中的条件。

    因为强连通分量中的点如果指向了另一个分量中的点,就不满足题目的条件了。

    所以我们要求的就是缩点之后,出度为0的强联通分量的所有点。

    代码 ————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    

    原文链接:https://blog.csdn.net/weixin_43236122/article/details/105405472

    //#include<bits/stdc++.h>
    #include<algorithm>
    #include<string.h>
    #include<stdio.h>
    #include<iostream>
    #include<queue>
    #include<map>
    #include<time.h>
    #define pb push_back
    #define read(a) scanf("%d",&a)
    #define out(a) printf("%d\n",a)
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int N=1e6+10;
    const int mod=1000000007;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    
    vector<int>vec[N],ans;
    int dfn[N],low[N],Stack[N],vis[N],bel[N],out[N];
    int top,tot,num;
    void tarjan(int u)
    {
        dfn[u]=low[u]=++tot;
        Stack[top++]=u;
        vis[u]=1;
        for(int i=0;i<vec[u].size();i++)
        {
            int v=vec[u][i];
            if(!dfn[v])
            {
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(vis[v]&&dfn[v]<low[u])
                low[u]=dfn[v];
        }
        if(dfn[u]==low[u])
        {
            int v;
            num++;
            do
            {
                v=Stack[--top];
                bel[v]=num;
                vis[v]=0;
            }
            while(u!=v);
        }
    }
    int main()
    {
        int n,m;
        while(~scanf("%d",&n)&&n)
        {
            memset(dfn,0,sizeof(dfn));
            memset(out,0,sizeof(out));
            memset(vis,0,sizeof(vis));
            num=top=tot=0;
            read(m);
            for(int i=1;i<=m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                vec[u].pb(v);
            }
            for(int i=1;i<=n;i++)
                if(!dfn[i]) tarjan(i);
            for(int i=1;i<=n;i++)
            {
                for(int j=0;j<vec[i].size();j++)
                {
                    int u=i,v=vec[i][j];
                    if(bel[u]==bel[v]) continue;
                    out[bel[u]]++;
                }
            }
            for(int i=1;i<=n;i++) vec[i].clear();
            for(int i=1;i<=n;i++)
                if(out[bel[i]]==0) printf("%d ",i);
            printf("\n");
        }
        return 0;
    }
    
    
    • 1

    信息

    ID
    1454
    时间
    1000ms
    内存
    64MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者