Electricity

题目大意

给定一个 nn 个点、mm 条边的无向图,试求从图中删去一个点后,图中最多有多少个连通分量。

数据范围:

n,m40000n,m≤40000

解题思路

首先要明白这题不是要你找割点,而是求图中删去一个点后,图中最多有多少个连通分量。

图中删去一个点后,图中连通分量个数 == 连通子图个数(cntncntn++ cuticut_i

cuticut_i 为删去点 ii 后,图中可以产生的连通分量。

判断条件

if (low[v] >= dfn[u])
{
  flag++;
  if((u != rt || flag > 1)) cut[u]++;
}

AC CODE

#include <bits/stdc++.h>
using namespace std;

struct Fastio
{
    template <typename T>
    inline Fastio operator>>(T &x)
    {
        x = 0;
        char c = getchar();
        while (c < '0' || c > '9')
            c = getchar();
        while (c >= '0' && c <= '9')
            x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
        return *this;
    }
    inline Fastio &operator<<(const char *str)
    {
        int cur = 0;
        while (str[cur])
            putchar(str[cur++]);
        return *this;
    }
    template <typename T>
    inline Fastio &operator<<(T x)
    {
        if (x == 0)
        {
            putchar('0');
            return *this;
        }
        if (x < 0)
            putchar('-'), x = -x;
        static int sta[45];
        int top = 0;
        while (x)
            sta[++top] = x % 10, x /= 10;
        while (top)
            putchar(sta[top] + '0'), --top;
        return *this;
    }

} io;

int n, m, rt, ans, cnt_node, cntn;

int cnt;
array<int, 2000005> head;
struct abc
{
    int to, nxt;
};
array<abc, 2000005> dd;

array<int, 2000005> dfn, low, cut;

inline void add(int u, int v)
{
    dd[++cnt].to = v;
    dd[cnt].nxt = head[u];
    head[u] = cnt;
}

inline void tarjan(int u)
{
    dfn[u] = low[u] = ++cnt_node;
    int flag = 0;
    for (int e = head[u]; e; e = dd[e].nxt)
    {
        int v = dd[e].to;
        if (!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[v], low[u]);
            if (low[v] >= dfn[u])
            {
                flag++;
                if ((u != rt || flag > 1))
                    cut[u]++;
            }
        }
        else
            low[u] = min(low[u], dfn[v]);
    }
}

void init()
{
    cnt = 0;
    cnt_node = 0;
    cntn = 0;
    ans = 0;
    head.fill(0);
    cut.fill(0);
    dfn.fill(0);
    low.fill(0);
}
signed main()
{
    while (1)
    {
        init();
        io >> n >> m;
        if (!n && !m)
            break;
        for (int i = 1; i <= m; ++i)
        {
            int u, v;
            io >> u >> v;
            u++;
            v++;
            add(u, v);
            add(v, u);
        }
        for (int i = 1; i <= n; ++i)
            if (!dfn[i])
            {
                tarjan(rt = i);
                cntn++;
            }
        for (int i = 1; i <= n; ++i)
            ans = max(ans, cntn + cut[i]);
        io << ans << "\n";
    }
    return 0;
}
posted @ 2021-08-06 08:44  蒟蒻orz  阅读(2)  评论(0编辑  收藏  举报  来源