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
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.
題目大意:
解題思路:
關於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));
}
}