K 度限制生成树:指定一个节点的度不能超过k 度.加边后,破圈.
<strong><span style="font-family:FangSong_GB2312;font-size:14px;">K度限制生成树
const int N=500;
struct node {
int a,b,c;
friend bool operator <(const node &a,const node &b){
return a.c<b.c;
}
}edge[N*N],ee; //edge 原图的边
int n,m,k,root; //点数,边数,限制度k,根root
vector <node> e[N],rt; //生成树的边,和root连出去的边
bool mark[N]; //标记root连出去的边
//---------------加MST的边-----------------------
void addedge(int u,int v,int w){
ee.b=v;ee.c=w;e[u].push_back(ee);
ee.b=u;ee.c=w;e[v].push_back(ee);
}
//------------------------Kruskal求MST(除root)------------------------
int pre[N];
int find_DS(int r){ //查询
if (r==pre[r]) return pre[r];
int fa=pre[r];
pre[r]=find_DS(pre[r]);
return pre[r];
}
bool merge_DS(int x,int y){ //合并
int fx=find_DS(x),fy=find_DS(y);
if (fx==fy){
return 0;
}
else {
pre[fx]=fy;
return 1;
}
}
int kruskal(){
int u,v,mst=0;
for (int i=0;i<=n;i++) pre[i]=i;
sort(edge+1,edge+1+m);
for (int i=1;i<=m;i++) {
u=edge[i].a;v=edge[i].b;
if (u==root||v==root) { //将和root相连的边加到rt数组中
if (v==root) swap(edge[i].a,edge[i].b);
rt.push_back(edge[i]);
}
else if (merge_DS(u,v)){ //加生成树的边(除root)
mst+=edge[i].c;
addedge(u,v,edge[i].c);
}
}
return mst;
}
//-----------------------------求K度生成树--------------------------------
bool vis[N];
node best[N];//best[v]为从root到v的链上最大边
void dfs(int u,node f){ //搜索最大边O(n)
if (vis[u]) return ;
vis[u]=1;best[u]=f;
for (int i=0;i<e[u].size();i++){
node ff=f;//父节点的最大边
int v=e[u][i].b,w=e[u][i].c;
if (w>ff.c) ff.a=u,ff.b=v,ff.c=w;
dfs(v,ff);
}
vis[u]=0;
}
void Remove (int u,int v){ //删除最大边
for (int i=0;i<e[u].size();i++){
if (e[u][i].b==v) {
e[u].erase(e[u].begin()+i);
return ;
}
}
}
int solve (int mst){
int i,u=root,v,w;
int d=0;//记录度
for (int i=0;i<rt.size();i++){ //最小生成树
v=rt[i].b;w=rt[i].c;
if (merge_DS(u,v)){
d++;mst+=w;
addedge(u,v,w);
mark[i]=1; //标记已经选中
}
}
//if (d>k) return -1;
while (d<k){
int tmp=0,j=0; //tmp最大差,j为和root相连要加入Tree的边
node max_e; //记录替换边
ee.c=-1;dfs(root,ee); //求最大边
for (int i=0;i<rt.size();i++){ //寻找替换边
if (mark[i]) continue; //已经在MST中了
v=rt[i].b;w=rt[i].c;
if (tmp<best[v].c-w){
tmp=best[v].c-w;
j=i;max_e=best[v];
}
}
if (tmp==0) break; //说明已经是MST了
mark[j]=1;
Remove(max_e.a,max_e.b);
Remove(max_e.b,max_e.a);
e[root].push_back(rt[j]);
d++,mst-=tmp;
}
return mst;
}
//----------------------初始化--------------------------
void init(){
n=0;
for (int i=0;i<=m*2;i++) e[i].clear();
rt.clear();
memset(mark,0,sizeof(mark));
memset(vis,0,sizeof(vis));
}</span></strong>
相关题目:
Poj1639 (K度生成树裸题)