hdu 4587 无向图求割点
1 /* 2 题意:给出一个无向图,求两个点,去除这两个点之后的连通分量数目最大 3 4 题解:无向图求割点 5 一开始在思考的时候想要先求出最大和次大的割点,然后发现两个割点如果相连的话比较难判断,在网上搜索题解发现 6 是通过先枚举所有点,然后再求出最大割点,然后求出最终答案,略显暴力,但是12s的时间,估计是绰绰有余了。。 7 */ 8 #include<iostream> 9 #include<cstdio> 10 #include<cstring> 11 12 using namespace std; 13 14 const int MAXV = 5005; 15 16 int dfn[MAXV],low[MAXV],head[MAXV],cut[MAXV]; 17 bool vis[MAXV]; 18 int cnt,EN; 19 20 struct Edge 21 { 22 int to,nxt; 23 }edge[MAXV<<1]; 24 25 void addedge(int cu,int cv) 26 { 27 edge[EN].to = cv; 28 edge[EN].nxt = head[cu]; 29 head[cu] = EN++; 30 } 31 32 void Tarjan(int u,int c) // 求割点 33 { 34 vis[u] = true; 35 dfn[u] = low[u] = ++cnt; 36 for(int i = head[u]; i != -1; i = edge[i].nxt) 37 { 38 int v = edge[i].to; 39 if (v == c) // 此处通过特判去除c点 40 continue; 41 if (dfn[v] == 0) { 42 Tarjan(v,c); 43 low[u] = min(low[u], low[v]); 44 if (low[v] >= dfn[u]) 45 { 46 cut[u]++; 47 } 48 } 49 else if (vis[v]) 50 low[u] = min(low[u], dfn[v]); 51 } 52 } 53 54 int main(void) 55 { 56 int n,m; 57 while(~scanf("%d%d",&n,&m)) 58 { 59 memset(head,-1,sizeof(head)); 60 EN=0; 61 while (m--) 62 { 63 int u,v; 64 scanf("%d%d",&u,&v); 65 addedge(u,v); 66 addedge(v,u); 67 } 68 69 int ans = 0; 70 for(int i=0; i<n; i++) 71 { 72 // 遍历分别去除n个点(在搜索过程中特判实现),然后再求割点使得切割数量最大 73 memset(dfn,0,sizeof(dfn)); 74 memset(vis,false,sizeof(vis)); 75 for(int j=0; j<n; j++) 76 cut[j] = 1; 77 int sum = 0; // 记录总共有多少个连通分量 78 cnt = 0; 79 for(int j=0; j<n; j++) 80 { 81 if (i != j && !vis[j]) 82 { 83 sum++; 84 cut[j] = 0; // 当前以j为根结点搜索,因此需要赋0 85 Tarjan(j,i); 86 } 87 } 88 for(int j=0; j<n; j++) 89 if (j != i) 90 { 91 ans = max(ans,sum+cut[j] - 1); // 求出符合的割点 92 } 93 } 94 printf("%d\n",ans); 95 } 96 return 0; 97 }