Codeforces Round #377 (Div. 2) F

前言:关于如何求双连通分量,我们可以在tarjan搜索时标记下所有桥的位置(双连通分量(可以认为是没有桥的无向图图)即可通过删去所有桥得到),那么怎么找桥呢,对于每一条搜索到的边u->x,如果low【u】>dfn【x】则说明u不能通过子图到达比x更早的节点,那么就说明该边是桥

题意:把一个无向图变成有向图,对于这个有向图来说,每个点的价值是它所有能到达的点的数量,要求使得所有点中最小的价值最大

题解:现学的边-双联通分量,先求一遍边-双联通分量,然后在每个双连通分量里dfs一边把双向边变成单向边,最后从点数最大的那个双连通分量开始dfs,删去反向边,易证最大的点数就是答案,然后直接输出单向边即可

#include<bits/stdc++.h>
#include<ext/rope>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;
using namespace __gnu_cxx;

const double g=10.0,eps=1e-7;
const int N=400000+10,maxn=100000+10,inf=0x3f3f3f;

map<int,int>ma[N];
map<int,int>ans[N];
vector<int>v[N];
int dfn[N],low[N];
int a[N],b[N];
int index,sz;
void tarjan(int u,int f)
{
    dfn[u]=low[u]=++index;
    for(int i=0;i<v[u].size();i++)
    {
        int x=v[u][i];
        if(x==f)continue;
        if(!dfn[x])
        {
            tarjan(x,u);
            low[u]=min(low[u],low[x]);
            if(low[x]>dfn[u])ma[u][x]=ma[x][u]=1;
        }
        else low[u]=min(low[u],dfn[x]);
    }
}
void init(int n)
{
    memset(dfn,0,sizeof dfn);
    memset(low,0,sizeof low);
    index=0;
    for(int i=1;i<=n;i++)
    {
        ma[i].clear();
        v[i].clear();
        ans[i].clear();
    }
}
void dfs(int u,int f)
{
    dfn[u]=1;
    sz++;
    for(int i=0;i<v[u].size();i++)
    {
        int x=v[u][i];
        if(!ma[x][u]&&x!=f)
        {
       //     cout<<u<<" "<<x<<endl;
            if(ans[x][u]&&ans[u][x])ans[x][u]=0;
            if(!dfn[x])dfs(x,u);
        }
    }
}
void dfs2(int u,int f)
{
    dfn[u]=1;
    for(int i=0;i<v[u].size();i++)
    {
        int x=v[u][i];
        if(!dfn[x])
        {
            if(ans[x][u]&&ans[u][x])ans[u][x]=0;
            dfs2(x,u);
        }
    }
}
int main()
{
    int n,m;
    cin>>n>>m;
    init(n);
    for(int i=0;i<m;i++)
    {
        cin>>a[i]>>b[i];
        ans[a[i]][b[i]]=ans[b[i]][a[i]]=1;
        v[a[i]].pb(b[i]);
        v[b[i]].pb(a[i]);
    }
    tarjan(1,-1);
    memset(dfn,0,sizeof dfn);
    int maxx=0,id;
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
        {
            sz=0;
            dfs(i,-1);
            if(maxx<sz)
            {
                maxx=sz;
                id=i;
            }
        }
    }
    memset(dfn,0,sizeof dfn);
    dfs2(id,-1);
    cout<<maxx<<endl;
    for(int i=0;i<m;i++)
    {
        if(ans[a[i]][b[i]])cout<<a[i]<<" "<<b[i]<<endl;
        else cout<<b[i]<<" "<<a[i]<<endl;
    }
    return 0;
}
/************
7 8
1 2
2 3
1 3
3 4
4 5
5 6
6 7
7 4
************/
View Code
原文地址:https://www.cnblogs.com/acjiumeng/p/7744852.html