HDU

来源:互联网 发布:js输出时间格式 编辑:程序博客网 时间:2024/06/13 18:16

题意:给出一张图,问从中任意去掉两个点及其邻接边,所有可能情况剩下的图中连通块的数量最大是多少。

思路:先枚举去电其中一个点,剩下的一个点用tarjan求无向图割点类似的方法求个最大值,具体就是当一个点能成为割点时,我们不是将其标记出来,而是将其计数器+1,最后取一个最大值就行了。

需要注意的就是当根节点为割点时,将其去掉以后得到的新连通块数量是son - 1.(son为搜索树上其儿子的数量)

这个题逼着我重新理解了一遍tarjan算法求无向图割边割点,也算是很有意义了。

代码:

#include<bits/stdc++.h>#define ll long long#define inf 0x3f3f3f3fusing namespace std;typedef pair<int,int> P;const int MAXN = 5010;int pre[MAXN], cnt;int dfn[MAXN], low[MAXN], block[MAXN], tid;int ban;struct node{int v, next;node() {}node(int _v, int _next) : v(_v), next(_next) {}}mp[MAXN << 1];void init(){memset(pre, -1, sizeof(pre));cnt = 0;}void add(int u, int v){mp[cnt] = node(v, pre[u]); pre[u] = cnt++;mp[cnt] = node(u, pre[v]); pre[v] = cnt++;}void dfs(int u, int fa){int v, son = 0;low[u] = dfn[u] = ++tid;for(int i = pre[u]; ~i; i = mp[i].next){v = mp[i].v;if(v == fa || v == ban) continue;if(!dfn[v]){son++;dfs(v, u);low[u] = min(low[u], low[v]);if(dfn[u] <= low[v])block[u]++;}else if(dfn[v] < low[u]) low[u] = dfn[v];}if(fa == -1)//注意这里cut[u]并非等于sonblock[u] = son - 1;}int solve(int n){int ans = 0, tmp;for(ban = 0; ban < n; ban++){tmp = tid = 0;memset(block, 0, sizeof(block));memset(dfn, 0, sizeof(dfn));for(int i = 0; i < n; i++){if(i == ban || dfn[i]) continue;dfs(i, -1);tmp++;}for(int i = 0; i < n; i++)if(i != ban)ans = max(ans, tmp + block[i]);}return ans;}int main(){int n, m, u, v;while(~scanf("%d %d", &n, &m)){init();for(int i = 0; i < m; i++){scanf("%d %d", &u, &v);add(u, v);}printf("%d\n", solve(n));} return 0;}



原创粉丝点击