给定一个无向的连通图,要求每个点去掉后连通分量的数目,然后输出连通分量最多的m个点。
分析:
先求出双连通分量,然后统计所有双连通分量中割顶出现的次数,最后求出的就是割顶去掉后剩下的双连通的数目,对于不是割顶的点,去掉后剩下的仍为双连通,所以结果就是1.
代码:
#include <iostream> #include <sstream> #include <cstdio> #include <climits> #include <cstring> #include <cstdlib> #include <string> #include <stack> #include <map> #include <cmath> #include <vector> #include <queue> #include <algorithm> #define esp 1e-6 #define pi acos(-1.0) #define pb push_back #define mp(a, b) make_pair((a), (b)) #define in freopen("in.txt", "r", stdin); #define out freopen("out.txt", "w", stdout); #define print(a) printf("%d ",(a)); #define bug puts("********))))))"); #define stop system("pause"); #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++) #define inf 0x0f0f0f0f using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int, int> pii; typedef vector<pii,int> VII; typedef vector<int>:: iterator IT; const int maxn = 10000 + 10; int pre[maxn], iscut[maxn], low[maxn], bccno[maxn], dfs_clock, bcc_cnt; VI g[maxn], bcc[maxn]; int ans[maxn], r[maxn]; stack<pii> S; bool cmp (const int &a, const int &b) { return ans[a] > ans[b] || (ans[b] == ans[a] && a < b); } int dfs(int u, int fa) { int lowu = pre[u] = ++dfs_clock; int child = 0; for(int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if(!pre[v]) { S.push(mp(u, v)); child++; int lowv = dfs(v, u); lowu = min(lowu, lowv); if(lowv >= pre[u]) { iscut[u] = 1; bcc_cnt++, bcc[bcc_cnt].clear(); for(;;) { pii x = S.top(); S.pop(); if(bccno[x.first] != bcc_cnt) { bccno[x.first] = bcc_cnt; bcc[bcc_cnt].pb(x.first); } if(bccno[x.second] != bcc_cnt) { bccno[x.second] = bcc_cnt; bcc[bcc_cnt].pb(x.second); } if(x.first == u && x.second == v) break; } } } else if(pre[v] < pre[u] && v != fa) { S.push(mp(u, v)); lowu = min(lowu, pre[v]); } } if(child == 1 && fa < 0) iscut[u] = 0; return low[u] = lowu; } void find_bcc(int n) { memset(pre, 0, sizeof(pre)); memset(iscut, 0, sizeof(iscut)); memset(bccno, 0, sizeof(bccno)); dfs_clock = bcc_cnt = 0; for(int i = 0; i < n; i++) if(!pre[i]) dfs(i, -1); } int main(void) { int n, m; while(scanf("%d%d", &n, &m), n||m) { for(int i = 0; i < maxn; i++) g[i].clear(); for(int i = 0; i < maxn; i++) r[i] = i; memset(ans, 0,sizeof(ans)); int u, v; while(scanf("%d%d", &u, &v), u>=0) { g[u].pb(v); g[v].pb(u); } find_bcc(n); for(int i = 1; i <= bcc_cnt; i++) for(int j = 0; j < bcc[i].size(); j++) { int x = bcc[i][j]; if(iscut[x]) ans[x]++ ; } for(int i = 0; i < n; i++) if(ans[i] == 0) ans[i] = 1; sort(r, r+n, cmp); for(int i = 0; i < m; i++) printf("%d %d ", r[i], ans[r[i]]); puts(""); } return 0; }