CodeForces 732F Tourist Reform

边双连通分量。

这题有一点构造的味道。一个有向图,经过强连通缩点之后会形成一个有向无环图。

如果将最大的强连通分量放在顶端,其余的强连通分量都直接或间接指向他,那么这样就构造出了符合要求的图。

接下来就是要去寻找强连通分量。对于一个无向图来说,每一个边-双联通分量都可以将每条边定向之后构造成一个强连通分量,$dfs$一遍即可。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<ctime>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-10;
void File()
{
    freopen("D:\in.txt","r",stdin);
    freopen("D:\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar();
    x = 0;
    while(!isdigit(c)) c = getchar();
    while(isdigit(c))
    {
        x = x * 10 + c - '0';
        c = getchar();
    }
}

const int maxn = 800000 + 5;
int n,m;

int pre[maxn], dfs_clock, bcc_cnt;
vector<int>G[maxn], bcc[maxn];

int belong[maxn],U[maxn],V[maxn],sz;
int flag[maxn],ff[maxn],gg[maxn],ge[maxn],dd[maxn];

int Tarjan(int u,int fa)
{
    int lowu=pre[u]=++dfs_clock;

    for(int i=0;i<G[u].size();i++)
    {
        int v=V[G[u][i]];
        if(!pre[v])
        {
            int lowv=Tarjan(v,u);
            lowu=min(lowu,lowv);

            if(lowv > pre[u]) ge[(G[u][i]+1)/2]=1;
        }
        else if(v!=fa) lowu=min(lowu,pre[v]);
    }

    return lowu;
}

void add(int a,int b)
{
    sz++; U[sz]=a; V[sz]=b;
    G[a].push_back(sz);
}

void DFS(int x,int y)
{
    flag[y]=1;
    for(int i=0;i<G[y].size();i++)
    {
        int v=V[G[y][i]];
        if(v==x) continue;
        if(ff[(G[y][i]+1)/2]==1) continue;
        ff[(G[y][i]+1)/2]=1;
        gg[G[y][i]]=1;
        if(flag[v]==0) DFS(y,v);
    }
}

void dfs(int x)
{
    belong[x]=bcc_cnt;
    for(int i=0;i<G[x].size();i++)
    {
        if(ge[(G[x][i]+1)/2]==1) continue;
        int v=V[G[x][i]];
        if(belong[v]!=0) continue;
        dfs(v);
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int a,b; scanf("%d%d",&a,&b);
        add(a,b); add(b,a);
    }

    for (int i = 1; i <= n; i++) if (!pre[i]) Tarjan(i, -1);

    for(int i=1;i<=n;i++)
    {
        if(belong[i]!=0) continue;
        bcc_cnt++; dfs(i);
    }

    for(int i=1;i<=n;i++) dd[belong[i]]++;

    int mx=0,idx=0;
    for(int i=1;i<=bcc_cnt;i++) if(dd[i]>mx) mx=dd[i],idx=i;

    for(int i=1;i<=n;i++) if(belong[i]==idx) { DFS(-1,i); break; }

    printf("%d
",mx);
    for(int i=1;i<=sz;i++)
        if(gg[i]) printf("%d %d
",V[i],U[i]);

    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/6379078.html