hdu4587TWO NODES(枚举+割点)
题目大意:给我们一个无向图,让我们删两个点,让剩下的强连通分量个数最多
思路:N只有5000,所以复杂度可以高一点,所以想到枚举删除一个点,然后对剩下的图
用求割点的方式,求出割去该点后能多出来的连通分量个数,即子树个数,要记得对根节点特判
AC代码:
#include<bits/stdc++.h> using namespace std; const int maxn = 25500; typedef long long ll; struct edge { int f, t, nxt; }e[maxn << 1]; int hd[maxn], tot; void add(int f, int t) { e[++tot] = { f,t,hd[f] }; hd[f] = tot; } int n, m; int low[maxn], dfn[maxn], cnt,no; int num[maxn];//割去该点的能多出来的联通分量个数 void init() { memset(hd, 0, sizeof(hd)); tot = 0; } void dfs(int u, int f) { low[u] = dfn[u] = ++cnt; int son = 0; for (int i = hd[u]; i; i = e[i].nxt) { int v = e[i].t; if (v == f||v==no) {continue;} if (!dfn[v]) { son++;//别写上面了,别问...问就是son表示子连通分量(树)个数 dfs(v, u); low[u] = min(low[u], low[v]); if (u!=f&&low[v] >= dfn[u]) {//是割点 num[u]++; } } else if (dfn[u]>dfn[v]) { low[u] = min(low[u], dfn[v]); } } if (u == f) {//根节点特判 num[u] = son - 1; } } int main() { //freopen("test.txt", "r", stdin); while (~scanf("%d%d", &n, &m)) { init(); while (m--) { int a, b; scanf("%d%d", &a, &b); add(a, b); add(b, a); } int ans=0; for (int i = 0; i < n; i++) {//枚举删除第一个点,然后求割掉每个点能多出来的联通分量 no = i; memset(dfn, 0, sizeof(dfn)); memset(num, 0, sizeof(num)); cnt = 0; int colnum = 0;//最初的图也可能是不是强联通的 for (int v = 0; v < n; v++) { if (!dfn[v]&&v!=no) { dfs(v, v); colnum++; } } for (int v = 0; v < n; v++) { if(v!=no)ans = max(ans, colnum + num[v]); } } printf("%d\n", ans); } return 0; }