Tarjan求割点——HDU 4587
来源:互联网 发布:云计算都招聘什么岗位 编辑:程序博客网 时间:2024/06/06 00:16
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4587
题意:从一个无向图中删除任意两个点,求能得到的连通分量的最大个数
分析:想要增加联通分量的个数,我们肯定想到是去删除割点。但是题中要删除2个点,所以我们第一次删除点时,不应该只奔着割点去,因为有可能删除一些非割点能够创造出新的割点,所以第一次删点应该枚举每一个点,第二次删除点就可以在删除第一个点的前提下,计算出每个割点删除后能增加多少个联通分量。
Tarjan计算删除某个割点增加的联通分量
void dfs(int u, int fa){ dfn[u] = low[u] = tmp++; vis[u] = 1; sum[u] = 0;//初始化为0,增加的联通分量数为0 for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].v; if(v!=del && v!=fa) { if(!vis[v]) { dfs(v,u); low[u] = min(low[v], low[u]); if(low[v] >= dfn[u]) sum[u]++;//如果有一条树边指向的子节点的low[v]>=dfn[u]则该点u一定为割点,且删除它后,可以增加一个联通分量 } else low[u] = min(low[u],dfn[v]); } } if(u==fa) sum[u]--;//根节点增加的联通分量减1,因为最开始计算了一个整体的联通分量。且若删除根节点没有增加连通分量(可能只有根节点1个点),那么根节点要被删除,即这个子图里没有点了,需要返回-1 if(ans<sum[u]) ans=sum[u]; return;}
- AC代码:
/************************************************************************* > File Name: test.cpp > Author: Akira > Mail: qaq.febr2.qaq@gmail.com ************************************************************************/#include <iostream>#include <sstream>#include <cstdio>#include <cstring>#include <string>#include <cstdlib>#include <algorithm>#include <bitset>#include <queue>#include <stack>#include <map>#include <cmath>#include <vector>#include <set>#include <list>#include <ctime>#include <climits>typedef long long LL;typedef unsigned long long ULL;typedef long double LD;#define MST(a,b) memset(a,b,sizeof(a))#define CLR(a) MST(a,0)#define Sqr(a) ((a)*(a))using namespace std;#define MaxN 5001#define MaxM MaxN*2#define INF 0x3f3f3f3f#define PI 3.1415926535897932384626const int mod = 1E9+7;const double eps = 1e-6;#define bug cout<<88888888<<endl;#define debug(x) cout << #x" = " << x << endl;struct Edge{ int u, v, next;}edge[MaxM];int cont,head[MaxN];int n,m;void add(int u, int v){ edge[cont].u = u; edge[cont].v = v; edge[cont].next = head[u]; head[u] = cont++;}int dfn[MaxN],low[MaxN],vis[MaxN];int sum[MaxN],ans,ret,del,tot,tmp;void dfs(int u, int fa){ dfn[u] = low[u] = tmp++; vis[u] = 1; sum[u] = 0; for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].v; if(v!=del && v!=fa) { if(!vis[v]) { dfs(v,u); low[u] = min(low[v], low[u]); if(low[v] >= dfn[u]) sum[u]++; } else low[u] = min(low[u],dfn[v]); } } if(u==fa) sum[u]--; if(ans<sum[u]) ans=sum[u]; return;}void solve(){ ans = -1;tot=0; CLR(vis); for(int i=1;i<=n;i++) { if(!vis[i] && i!=del) { tmp = 0; dfs(i,i); tot++; } } if(ret < ans + tot) ret = ans+tot; return;}void init(){ MST(head,-1); cont = 0; CLR(dfn),CLR(low),CLR(sum); ret = 0;}int main(){ //std::ios::sync_with_stdio(false); while(~scanf("%d%d", &n, &m)) { init(); int a,b; for(int i=0;i<m;i++) { scanf("%d%d", &a, &b); a++,b++; add(a,b),add(b,a); } for(int i=1;i<=n;i++) { del = i; solve(); } printf("%d\n", ret); } //system("pause");}
0 0
- Tarjan求割点——HDU 4587
- hdu 4587(tarjan)
- Tarjan 缩点——HDU 5934
- 【双连通分量(tarjan)+树形dp】HDU-2242-考研路茫茫——空调教室
- 2-SAT(Tarjan)—— Get Luffy Out *(HDU 1816)
- hdu 2242 考研路茫茫——空调教室 【Tarjan缩点+树上DP】 解题报告
- hdu 1269 tarjan
- hdu 2586 Tarjan离线
- hdu 4547(tarjan LCA)
- hdu 4547(tarjan LCA)
- hdu 4547(tarjan LCA)
- hdu 1269 (tarjan)
- HDU 5266 【tarjan--水】
- HDU 1827 Tarjan
- HDU 1269 Tarjan
- HDU 3394Railway( tarjan)
- hdu 4547(LCA+Tarjan)
- hdu Summer Holiday(tarjan)
- 获取最小的未被占用的串口号
- 二叉树的遍历初学
- 对集群进行集中管理
- 二叉树的中序遍历
- C++ 让人迷惑的复制构造函数和赋值运算符的区别
- Tarjan求割点——HDU 4587
- Permission is only granted to system apps
- singleton
- 七步精通Python机器学习
- MyBatis动态sql详解(一)
- 设计模式原则—开闭原则(OCP)
- 读书笔记之适配器模式
- 二叉树的后序遍历--非递归实现
- java Stringbuffer的使用