您的位置:首页 > 运维架构

TopCoder SRM687 div1 500

2016-04-13 21:59 309 查看
  题意是已知一个无向图所有点对间的最小割,构造一个合法的原图。

  看了题解得知有个叫Gomory-Hu tree的东西,即最小割树。解题要点是,你要知道一个图的所有点对最小割,一定能用一棵树做到。于是我们的目标变为构造这样一棵树。

  我们可以用分治法,不断把当前点集划分为两个点集,其中两个点集的点之间流量是当前最小,不断分治直到集合只剩一个点。

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const int maxn = 55;

int n;
int w[maxn][maxn];

vector<int> adj[maxn];
vector<int> adjw[maxn];

bool ok = 1;

void fun(set<int> s){
if(s.size()<2)return;

int MIN = 1e9;

int U,V;
for(int u:s){
for(int v:s){
if(u==v)continue;
if(w[u][v]<MIN){
MIN = w[u][v];
U=u;
V=v;
}
}
}

set<int> uSet;
set<int> vSet;
uSet.insert(U);
vSet.insert(V);

for(int q:s){
if(q==U || q==V)continue;
if(w[U][q]==MIN){
vSet.insert(q);
}else{
uSet.insert(q);
}
}

for(int u:uSet){
for(int v:vSet){
if(w[u][v]!=MIN){
ok=0;
}
}
}
adj[U].push_back(V);
adjw[U].push_back(MIN);

fun(uSet);
fun(vSet);
}

class AllGraphCuts{
public:
vector<int> findGraph(vector<int> x){
n = sqrt(x.size());
int MAX = -1;

set<int> oriSet;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
w[i][j] = x[i*n+j];
if(i==j){
if(w[i][j]){
ok=0;
}
continue;
}
if(j<i){
if(w[i][j]!=w[j][i])ok=0;
}
if(w[i][j]>MAX){
MAX = w[i][j];
}
}
oriSet.insert(i);
}
fun(oriSet);
vector<int> ans;
if(!ok){
cout<<"-1"<<endl;
ans.push_back(-1);
return ans;
}
for(int i=0;i<n;i++){
//w*n*n + i*n + j
for(int k=0;k<adj[i].size();k++){
int j = adj[i][k];
int ww = adjw[i][k];
ans.push_back(ww*n*n+i*n+j);
}
}
return ans;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  最小割树