电力

// 电力.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
/*
https://ac.nowcoder.com/acm/contest/963/F
https://loj.ac/s/2396894

求一个无向图删除一个点之后,联通块最多有多少。
输入描述:
多组数据。第一行两个整数P,C表示点数和边数。
接下来C行每行两个整数p1,p2,表示p1与p2有边连接,保证无重边。读入以0 0结束。
输出描述:
输出若干行,表示每组数据的结果。

3 3
0 1
0 2
2 1
4 2
0 1
2 3
3 1
1 0
0 0


1
2
2

1≤P≤10000,C≥0,0≤p1,p2<P

*/
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;


const int N = 10010, M = 30010;
int h[N], e[M], ne[M], idx;
int dfn[N], low[N], timestamp;
int n, m, root;
int ans;

void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void tarjan(int u) {
    dfn[u] = low[u] = ++timestamp;
    int flag = 0; int cnt = 0;
    for (int i = h[u]; i != -1; i = ne[i]) {
        int k = e[i];
        if (!dfn[k]) {
            tarjan(k);
            low[u] = min(low[u], low[k]);
            if (low[k] >= dfn[u]) {
                cnt++;
            }
        }
        else {
            low[u] = min(low[u], dfn[k]);
        }
    }
    if (root != u) cnt++;
	ans = max(ans, cnt);
}


void solve() {
    for (int i = 0; i < m; i++) {
        int a, b;  cin >> a >> b;
        if (a == b) continue;
        add(a, b); add(b, a);
    }
    int cnt = 0;
    for (int i = 0; i < n; i++) {
        if (!dfn[i]) {
            root = i; cnt++;
            tarjan(root);
        }
    }

    cout << cnt + ans - 1 << endl;
}


int main()
{
    while (1) {
        cin >> n >> m; if (n + m == 0) break;
        memset(h, -1, sizeof h);
		memset(dfn, 0, sizeof dfn); 
		memset(low, 0, sizeof low);
        idx = 0; timestamp = 0; root = -1; ans = 0;

        solve();
    }

    return 0;
}

posted on 2025-08-13 10:16  itdef  阅读(7)  评论(0)    收藏  举报

导航