【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;
}

原文地址:https://www.cnblogs.com/valk3/p/13297219.html