//poj 1639
int g[N][N];
int clo[N],dis[N],pre[N];
int n,rt;
int prim(int s,int id){
dis[s]=0;
int ans=0;
while(1){
int idx=-1,tmp=INF;
for(int i=0;i<n;i++)if(!clo[i]&&dis[i]<tmp){
idx=i,tmp=dis[i];
}
if(idx==-1)return ans;
ans+=dis[idx];
clo[idx]=id;
for(int i=0;i<n;i++)if(!clo[i]&&dis[i]>g[idx][i]){
dis[i]=g[idx][i];
pre[i]=idx;
}
}
}
void dfs(int u,int f){
if(u==rt)return ;
dfs(pre[u],u);
pre[u]=f;
}
int mx[N],sta[N],top;
void update(){
memset(mx,-1,sizeof(mx));
mx[rt]=0;
for(int i=0;i<n;i++)if(mx[i]==-1){
top=0;
int j=i;
while(mx[j]==-1){
sta[top++]=j;
j=pre[j];
}
sta[top++]=j;
for(int k=top-2;k>=0;k--){
int u=sta[k],v=sta[k+1];
mx[u]=max(mx[v],g[u][v]);
}
}
}
int fst[N];
int ktree(int k){
memset(clo,0,sizeof(clo));
memset(dis,0x3f,sizeof(dis));
clo[rt]=1;
int cnt=0,ans=0;
pre[rt]=rt;
for(int i=0;i<n;i++)if(!clo[i]){
ans+=prim(i,++cnt);
pre[i]=rt;
}
if(cnt>k)return -1;
memset(fst,-1,sizeof(fst));
for(int i=0;i<n;i++)if(i!=rt){
int id=clo[i];
int idx=fst[id];
if(idx==-1||g[rt][idx]>g[rt][i]){
fst[id]=i;
}
}
for(int i=1;i<=cnt;i++){
if(g[rt][fst[i]]==INF)return -1;
ans+=g[rt][fst[i]];
g[rt][fst[i]]=g[fst[i]][rt]=0;
dfs(fst[i],rt);
}
update();
k-=cnt;
while(k--){
int id=-1,tmp=INF;
for(int i=0;i<n;i++)if(i!=rt&&g[rt][i]!=0&&g[rt][i]!=INF&&g[rt][i]-mx[i]<tmp){
tmp=g[rt][i]-mx[i];
id=i;
}
if(id==-1)break;
if(tmp>=0)break;
ans+=tmp;
g[rt][id]=g[id][rt]=0;
int p=id;
for(int i=id;i!=rt;i=pre[i]){
if(g[i][pre[i]]>g[p][pre[p]]){
p=i;
}
}
pre[p]=rt;
dfs(id,rt);
update();
}
return ans;
}
k度限制最小生成树
最新推荐文章于 2021-02-10 14:41:20 发布