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 }

 

posted @ 2014-03-29 17:18  辛力啤  阅读(416)  评论(0编辑  收藏  举报