题目大意
一副无向图,给定任意两点间最小割,请构造出这样的图,或判断无解。
构造
显然构造出最小割树即可。
容易发现最小割树一定是一颗最大生成树。
不同的最大生成树之间任意两点间最小割不变。
因此做一颗最大生成树,看它是否满足条件即可。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100+10,inf=1000000000;
struct dong{
int x,y,z;
friend bool operator <(dong a,dong b){
return a.z>b.z;
}
} edge[maxn*maxn];
int dis[maxn][maxn],fa[maxn],data[maxn],zz[maxn],rk[maxn],ans[maxn][3];
bool bz[maxn];
int i,j,k,l,t,n,m,tot,top;
bool czy;
int getfa(int x){
return fa[x]?getfa(fa[x]):x;
}
void merge(int x,int y,int z){
top++;
ans[top][0]=x;ans[top][1]=y;ans[top][2]=z;
x=getfa(x);y=getfa(y);
if (rk[x]<rk[y]) swap(x,y);
fa[y]=x;
data[y]=z;
if (rk[x]==rk[y]) rk[x]++;
}
int ask(int x,int y){
int t=inf;
int j=x;
while (j){
bz[j]=1;
zz[j]=t;
t=min(t,data[j]);
j=fa[j];
}
t=inf;
j=y;
while (j){
if (bz[j]) break;
t=min(t,data[j]);
j=fa[j];
}
t=min(t,zz[j]);
j=x;
while (j){
bz[j]=0;
j=fa[j];
}
return t;
}
int main(){
freopen("cut.in","r",stdin);freopen("cut.out","w",stdout);
scanf("%d",&n);
fo(i,1,n)
fo(j,1,n){
scanf("%d",&dis[i][j]);
if (i!=j){
tot++;
edge[tot].x=i;
edge[tot].y=j;
edge[tot].z=dis[i][j];
}
}
sort(edge+1,edge+tot+1);
fo(i,1,tot){
j=edge[i].x;k=edge[i].y;l=edge[i].z;
if (getfa(j)!=getfa(k)) merge(j,k,l);
}
czy=1;
fo(i,1,n-1){
fo(j,i+1,n)
if (ask(i,j)!=dis[i][j]){
czy=0;
break;
}
if (!czy) break;
}
if (!czy) printf("-1\n");
else{
printf("%d\n",n-1);
fo(i,1,n-1) printf("%d %d %d\n",ans[i][0],ans[i][1],ans[i][2]);
}
}

本文介绍了一种构造无向图的方法,该图需满足任意两点间的最小割条件。文章详细阐述了如何通过构建一棵最大生成树来实现这一目标,并提供了一段C++代码示例。
879

被折叠的 条评论
为什么被折叠?



