• 【Codeforces-118-E】Bertown roads tarjan | DFS树


    E. Bertown roads

    题意

    给出一个 n 个点,m 条边的无向图,现在让你给所有的边一个方向,判断是否整个图是否可以变成一个强连通分量,如果可以输出所有的边的方向,否则输出 0 。

    思路

    首先判断什么时候不可以。

    那就是当这个图存在桥的时候。

    所以我们可以先使用 tarjan 找桥,如果找不到就可以。

    边的方向我们可以进行一遍 dfs 。

    找桥的时候也可以使用 DFS树 。

    DFS树 代码

    #include<bits/stdc++.h>
    #define pb push_back
    const int N=1e6+10;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    
    struct Edge
    {
        int to,next,flag;//flag用来标记这条边的方向
    } edge[N*2];
    int head[N],vis[N],dp[N],tot,dep;
    void add(int u,int v)
    {
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int up[N],down[N];//up[i] 和 down[i] 分别表示 从点 i 向上的非树边和向下的非树边
    void dfs(int u,int fa)
    {
        vis[u]=++dep;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].to;
            if(v==fa) continue;
            if(vis[v])
            {
                if(vis[u]<vis[v]) continue;
                edge[i^1].flag=1;
                edge[i].flag=0;
                up[u]++;
                down[v]++;
            }
            else
            {
                dfs(v,u);
                edge[i].flag=0;
                edge[i^1].flag=1;
            }
        }
        --dep;
    }
    void dfs2(int u,int fa)
    {
        vis[u]=1;
        dp[u]=up[u]-down[u];
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if((v==fa)||vis[v]) continue;
            dfs2(v,u);
            dp[u]+=dp[v];
        }
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1,u,v; i<=m; i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
        dfs(1,1);
        memset(vis,0,sizeof(vis));
        dfs2(1,1);
        for(int i=2;i<=n;i++)
        {
            if(!dp[i])
            {
                printf("0
    ");
                return 0;
            }
        }
        for(int u=1; u<=n; u++)
        {
            for(int j=head[u]; j!=-1; j=edge[j].next)
            {
                int v=edge[j].to;
                if(u>v)
                {
                    if(edge[j].flag)
                        printf("%d %d
    ",v,u);
                    else
                        printf("%d %d
    ",u,v);
                }
            }
        }
        return 0;
    }
    /*
    */
    

    tarjan 代码

    #include<bits/stdc++.h>
    #define pb push_back
    const int N=1e6+10;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    
    int low[N],dfn[N],vis[N],tot,bri;
    vector<int>g[N];
    vector<pair<int,int> >ans;
    void tarjan(int u,int fa)
    {
        low[u]=dfn[u]=++tot;
        int cnt=0;
        for(int v:g[u])
        {
            if(v==fa&&cnt==0)
            {
                cnt++;
                continue;
            }
            if(!dfn[v])
            {
                tarjan(v,u);
                low[u]=min(low[u],low[v]);
                if(dfn[u]<low[v])
                {
                    bri++;
                    return ;
                }
            }
            else
                low[u]=min(low[u],dfn[v]);
        }
    }
    void dfs(int u,int fa)
    {
        vis[u]=++tot;
        for(int v:g[u])
        {
            if(v==fa)
                continue;
            if(!vis[v])
            {
                ans.pb(make_pair(u,v));
                dfs(v,u);
            }
            else if(vis[v]<vis[u])
                ans.pb(make_pair(u,v));
        }
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1,u,v; i<=m; i++)
        {
            scanf("%d%d",&u,&v);
            g[u].pb(v),g[v].pb(u);
        }
        tarjan(1,1);
        if(bri)
            printf("0
    ");
        else
        {
            dfs(1,-1);
            for(auto i:ans)
                printf("%d %d
    ",i.first,i.second);
        }
        return 0;
    }
    
    
  • 相关阅读:
    【ASP.NET 进阶】根据IP地址返回对应位置信息
    【网络文摘】编程的智慧
    【ASP.NET 类库】当你懒得用 Json+Ajax 时,可以试试 AjaxPro
    【iOS 初见】第一个简单的 iOS 应用
    【C#】C# 实现发送手机短信
    【网络文摘】一家公司要了你后,凭什么给你开高工资?
    深入理解Java虚拟机01--概述
    Java虚拟机(五)Java的四种引用级别
    OkHttp3源码详解(六) Okhttp任务队列工作原理
    OkHttp3源码详解(五) okhttp连接池复用机制
  • 原文地址:https://www.cnblogs.com/valk3/p/13297219.html
Copyright © 2020-2023  润新知