hdu 4654 k-edge connected components

来源:互联网 发布:c语言 true false 编辑:程序博客网 时间:2024/05/21 00:47

k-edge connected components

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 41    Accepted Submission(s): 25


Problem Description
Efficiently computing k-edge connected components in a large graph G = (V, E), where V is the vertex set and E is the edge set, is a long standing research problem. It is not only fundamental in graph analysis but also crucial in graph search optimization algorithms. Computing k-edge connected components has many real applications. For example, in social networks, computing k-edge connected components can identify the closely related entities to provide useful information for social behavior mining. In a web-link based graph, a highly connected graph may be a group of web pages with a high commonality, which is useful for identifying the similarities among web pages. In computational biology, a highly connected subgraph is likely to be a functional cluster of genes for biologist to conduct the study of gene microarrays. Computing k-edge connected components also potentially contributes to many other technology developments such as graph visualization, robust detection of communication networks, community detection in a social network.

Clearly, if a graph G is not k-edge connected, there must be a set C of edges, namely a cut, such that the number |C| of edges in C is smaller than k and the removal of the edges in C cuts the graph G into two disconnected subgraphs G1 and G2. A connected component is a maximal connected subgraph of G. Note that each vertex belongs to exactly one connected component, as does each edge.

Now, we give you a undirected graph G with n vertices and m edges without self-loop or multiple edge, your task is just find out the number of k-edge connected components in G.
 

Input
Multicases. 3 integer numbers n, m and k are described in the first line of the testcase.(3≤n≤100, 1≤m≤n×(n-1)/2,2≤k≤n)The following m lines each line has 2 numbers u, v describe the edges of graph G.(1≤u,v≤n,u≠v)
 

Output
A single line containing the answer to the problem.
 

Sample Input
5 6 31 32 31 42 41 52 59 11 21 21 32 34 54 65 67 87 98 91 41 716 30 31 21 31 42 32 43 45 65 75 86 76 87 89 109 119 1210 1110 1211 1213 1413 1513 1614 1514 1615 161 52 61 92 101 13
2 14

Sample Output
534

 题目大意:

找出k联通分量的个数,k联通分量的意思是全局最小割的大小大于等于k。

解题思路:

Stoer-Wagner算法可以O(n^3)求全局最小割,一次Stoer-Wagner可以求出来当前图的全局最小割cut,如果cut>=k那么当前图就是k联通分量了,返回1;否则按照SW算法求出来的最小割来把当前图一分为二,递归下去求这两个图的k联通分量的个数。
伪代码:
Solve(G)
cut<--Stoer-Wagner(G)
if cut < k return 1
else return solve(G1)+solve(G2)


关于Stoer-Wagner算法:

求全局最小割的算法很简单且容易证明,首先算法基于一个事实,对于图G,如果我们知道S,T两点的最小割记为s-t-cut,那么这个s-t-cut可能是G的全局最小割也可能不是。如果不是的话,我们即使把这两个点合并也不会影响答案,所以就把这两个点合并好了。这样n-1次之后就可以把G缩为一个点了,这个过程中一定可以求出来正解。


所以我们可以每次随便找两个点s,t求它们的最小割,然后更新答案,然后把这两个点合并,直到剩一个点为止。

找S-T-CUT的方法类似求最大生成树,具体还是看这个论文:http://docs.google.com/fileview?id=0BwxLvD9mcDNtMjk3MWVkMTAtZjMzNi00ZWE3LTkxYjQtYTQwNzcyZTk3Njk2&hl=en

还有这个博客:http://www.cppblog.com/RyanWang/archive/2009/08/18/93748.html

代码:

#include<cstdio>#include<cstring>#include<queue>#include<iostream>using namespace std;const int INF = 1000000;const int N  = 110;int side[N][N];int grid[N][N];int w[N];bool vis[N];bool deleted[N];bool choose[N];int K;queue<int>qa,qb;vector<int>nodes[N];int prim(int k,int n,int &s,int &t){s=0;while(deleted[s])s++;for(int i=0;i<n;i++){w[i]=grid[s][i];vis[i]=false;}vis[s]=true;int p;int Max;for(int i=1;i<k;i++){Max=-INF;for(int j=0;j<n;j++)if(!vis[j]&&!deleted[j]){if(w[j]>Max){Max=w[j];p=j;}}if(i==k-2)s=p;if(i==k-1)t=p;vis[p]=true;for(int i=0;i<n;i++)if(!vis[i]&&!deleted[i]){w[i]+=grid[i][p];}}return w[t];}int stoerwagner(int n){if(n<=1)return 0;int min_cut=INF,s,t;for(int i=0;i<n;i++){deleted[i]=false;nodes[i].clear();nodes[i].push_back(i);}for(int i=1;i<n;i++){int cut=prim(n-i+1,n,s,t); if(cut<min_cut){min_cut=cut;for(int j=0;j<n;j++)choose[j]=0;for(int j=0;j<nodes[t].size();j++)choose[nodes[t][j]]=1;}for(int i=0;i<nodes[t].size();i++){nodes[s].push_back(nodes[t][i]);}deleted[t]=true;for(int i=0;i<n;i++){if(i==s)continue;if(!deleted[i]){grid[s][i]+=grid[t][i];grid[i][s]+=grid[i][t];}}}for(int i=0;i<n;i++){if(choose[i])qa.push(i);else qb.push(i);}return min_cut;}int solve(vector<int> a){int n=a.size();if(n<=1)return 1;int t;for(int i=0;i<n;i++)for(int j=0;j<n;j++){grid[i][j]=side[a[i]][a[j]];}if(stoerwagner(n)>=K){while(!qa.empty())qa.pop();while(!qb.empty())qb.pop();return 1;}vector<int>x,y;while(!qa.empty()){x.push_back(a[qa.front()]);qa.pop();}while(!qb.empty()){y.push_back(a[qb.front()]);qb.pop();};return solve(x)+solve(y);}int main(){int n,m;while(~scanf("%d%d%d",&n,&m,&K)){memset(side,0,sizeof(side));while(m--){int u,v;scanf("%d%d",&u,&v);u--;v--;side[u][v]=side[v][u]=1;}vector<int>graph;for(int i=0;i<n;i++){graph.push_back(i);}printf("%d\n",solve(graph));}}


原创粉丝点击