[题解] [JSOI2013] 强连通图

Posted ztlztl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解] [JSOI2013] 强连通图相关的知识,希望对你有一定的参考价值。

题面

题解

结论题

第一问直接 tarjan

第二问就是 tarjan 后缩点, DAG 中入度为 0 的点和出度为 0 的点的个数取 (min)

Code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
const int N = 5000005; 
using namespace std;

int n, m, dfn[N], low[N], head[N], stk[N], instk[N], sz[N], bl[N], out[N], in[N], ans, cnt, tot, top;
struct edge { int u, v, to, nxt; } e[N]; 

template < typename T >
inline T read()
{
    T x = 0, w = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * w; 
}

inline void adde(int u, int v) { e[++cnt] = (edge) { u, v, v, head[u] }, head[u] = cnt; }

void tarjan(int u)
{
    dfn[u] = low[u] = ++cnt, instk[stk[++top] = u] = 1;
    for(int v, i = head[u]; i; i = e[i].nxt)
    {
    v = e[i].to;
    if(!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]); 
    else if(instk[v]) low[u] = min(low[u], dfn[v]); 
    }
    if(low[u] >= dfn[u])
    {
    int x; tot++; 
    do
    {
        instk[x = stk[top--]] = 0; 
        sz[bl[x] = tot]++; 
    }
    while(x != u); 
    }
}

int main()
{
    n = read <int> (), m = read <int> ();
    for(int u, v, i = 1; i <= m; i++)
    {
    u = read <int> (), v = read <int> ();
    adde(u, v); 
    }
    cnt = 0;
    for(int i = 1; i <= n; i++)
    if(!dfn[i]) tarjan(i); 
    for(int i = 1; i <= tot; i++) ans = max(ans, sz[i]);
    printf("%d
", ans); 
    for(int u, v, i = 1; i <= m; i++)
    if(bl[u = e[i].u] != bl[v = e[i].v]) out[bl[u]]++, in[bl[v]]++; 
    ans = 0, cnt = 0; 
    for(int i = 1; i <= tot; i++)
    {
    if(!in[i]) ans++; 
    if(!out[i]) cnt++; 
    }
    printf("%d
", max(ans, cnt)); 
    return 0; 
}

以上是关于[题解] [JSOI2013] 强连通图的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2208: [Jsoi2010]连通数(dfs)

BZOJ2208 [Jsoi2010]连通数

HDU 1269 迷宫城堡 最大强连通图题解

P4306 [JSOI2010]连通数

bzoj1051题解

小白入门向tarjan算法+codevs1332题解报告