poj1639最小度限制生成树(kruscal+邻接表)

原创 2011年08月13日 11:51:35

一、.思路

设限制结点为des.

 1. 求去掉des的最小生成树,此时求出来的是最小生成森林

 2.添加des到各连通分量的边,当然取最小的边。

 3.此时得到m度的生成树,我们要求的是小于等于k度的最小生成树,此时我们可以用来调整的边只有k-m条,

注意我们不一定要强制添加k-m条从des出发的边,并删除与其构成环的最大的边,而是如果在可调整的范围内(满足度限制要求<=k)已经是最小的生成树

就可以直接退出。

这里给出算法的主过程,方便大家理解!

思路参考:国家集训队论文《最小生成树问题的拓展》

代码参考:http://www.cnblogs.com/ylfdrib/archive/2010/08/21/1805505.html

                    http://happylch21.blog.163.com/blog/static/16563975920113224491211/

int kDegreeMinTree()
    {
        int cost=0;
        cost+=kruscal();
        int m;
        cost+=mDegreeMinTree(m);
        cost+=expandToKDegree(k-m);
        return cost;
    }


二、.代码


#include<cstdio>
#include<iostream>

using namespace std;
//   freopen("data.in","r",stdin);

#include<algorithm>
#include<cstring>
#define N 25
#define M N*N//double
#define MAX 1000000000
struct Edge
{
    int u,v,next;
    int w;
} edge[M];

bool cmp(const int &a,const int &b)
{
    return edge[a].w<edge[b].w;
}
struct Graph
{
    int index[M],len;
    int first[N];
    bool branch[M];
    int _V,_E,des;//!!
    int k;
    int father[N];//!!前后两次的含义不一样,第一次是作为并查的顶点,第二次是作为某一条边的父边
    int best[N];

    char brother[25][15];
    char t[15];

    void initial(int m)
    {
        _V=0;
        _E=0;
        memset(first,-1,sizeof(first));
    }
    int find()
    {
        for(int i=0; i<_V; i++)
        {
            if(strcmp(brother[i],t)==0)return i;
        }
        strcpy(brother[_V],t);//!!
        return _V++;
    }
    void createGraph(int m)
    {
        initial(m);

        while(m--)
        {
            scanf("%s",t);
            int u=find();
            scanf("%s",t);
            int v=find();
            int w;
            scanf("%d",&w);
            add(u,v,w);
            add(v,u,w);
        }

        for(int i=0; i<_V; i++)
        {
            if(strcmp("Park",brother[i])==0)
            {
                des=i;
                break;
            }
        }
        scanf("%d",&k);
    }

    void add(int u,int v,int w)
    {
        edge[_E].u=u;
        edge[_E].v=v;
        edge[_E].w=w;
        edge[_E].next=first[u];
        first[u]=_E;
        _E++;
    }

    int findx(int u)
    {
        if(father[u]==u)return u;
        else return father[u]=findx(father[u]);
    }
    void Union(int x,int y)
    {
        father[x]=father[y];
    }
    int kruscal()
    {
        int cost=0;
        len=_E>>1;
        for(int i=0; i<len; i++)index[i]=i<<1;
        sort(index,index+len,cmp);

        memset(branch,0,sizeof(branch));
        for(int i=0; i<_V; i++)father[i]=i;
        for(int i=0; i<len; i++)
        {
            int e=index[i],u=edge[e].u,v=edge[e].v;
            if(u==des||v==des)continue;
            int root1=findx(u),root2=findx(v);
            if(root1!=root2)
            {
                branch[e]=branch[e^1]=true;
                cost+=edge[e].w;
                Union(root1,root2);
            }
        }
        return cost;
    }

    int mDegreeMinTree(int &m)
    {
        m=0;
        int cost=0;
        while(1)
        {
            int minE=-1;
            for(int e=first[des]; e!=-1; e=edge[e].next)
            {
                int v=edge[e].v;
                int rootV=findx(v);
                if(rootV!=des)
                {
                    if(minE==-1||edge[minE].w>edge[e].w)minE=e;
                }
            }
            if(minE==-1)break;
            m++;
            cost+=edge[minE].w;
            branch[minE]=branch[minE^1]=true;
            Union(findx(edge[minE].v),des);//!!
        }
        return cost;
    }

    void calFather(int u)
    {
        for(int e=first[u]; e!=-1; e=edge[e].next)
        {
            if(branch[e])
            {
                father[edge[e].v]=e;
                branch[e]=branch[e^1]=false;
                calFather(edge[e].v);
                branch[e]=branch[e^1]=true;//!!恢复
            }
        }
    }
    void dfs(int u)
    {
        int fE=father[u],fP=edge[fE].u;
        if(fP!=des)
        {
            int e=best[fP];
            if(e==-1 || edge[fE].w>edge[e].w)best[u]=fE;
            else best[u]=e;
        }
        for(int e=first[u]; e!=-1; e=edge[e].next)
        {
            if(branch[e])
            {
                branch[e]=branch[e^1]=false;
                dfs(edge[e].v);
                branch[e]=branch[e^1]=true;
            }
        }
    }

    int expandToKDegree(int rest)
    {
        int cost=0;
        calFather(des);
        while(rest)
        {
            memset(best,-1,sizeof(best));

            for(int e=first[des]; e!=-1; e=edge[e].next)
            {
                int v=edge[e].v;
                if(edge[father[v]].u==des)dfs(v);//!!best[v]=-1;恒立
            }

            int minE=-1,minCost=MAX;
            for(int e=first[des]; e!=-1; e=edge[e].next)
            {
                if(!branch[e])
                {
                    int v=edge[e].v;
                    int curCost=edge[e].w-edge[best[v]].w;
                    if(curCost<0&&minCost>curCost)//!!
                    {
                        minCost=curCost;
                        minE=e;
                    }
                }
            }

            if(minE==-1)return cost;
            else
            {
                int v=edge[minE].v;
                int other=best[v];
                cost+=minCost;
                branch[minE]=branch[minE^1]=true;
                branch[other]=branch[other^1]=false;
                calFather(v);//!!
                rest--;
            }
        }
        return cost;
    }

    int kDegreeMinTree()
    {
        int cost=0;
        cost+=kruscal();
        int m;
        cost+=mDegreeMinTree(m);
        cost+=expandToKDegree(k-m);
        return cost;
    }
    void printTree()
    {
        for(int e=0; e<_E; e+=2)
        {
            if(branch[e])cout<<edge[e].u<<' '<<edge[e].v<<' '<<edge[e].w<<endl;
        }
        cout<<endl;
    }
    void printEdge(int *a,char *s)
    {
        printf("%s\n",s);
        for(int u=0; u<_V; u++)
        {
            cout<<u<<' '<<endl;
            int e=a[u];
            cout<<edge[e].u<<' '<<edge[e].v<<' '<<edge[e].w<<endl;
        }
        cout<<endl;
    }
} net;

int main()
{
    //  freopen("data.in","r",stdin);
    int m;
    cin>>m;
    net.createGraph(m);
    printf("Total miles driven: %d\n",net.kDegreeMinTree());
    return 0;
}


poj1639 Picnic Planning 限制顶点度数的MST

题意: 有n个兄弟去野餐,目的地为Park。每个人可以选择直接去Park,也可以选择去其他人家,和他一起坐车去Park。 每个人家的停车位没有限制,但是Park的停车数不能超过k。问所有人的最短路程。...
  • u011265346
  • u011265346
  • 2015-01-20 16:43:49
  • 710

最小K度限制生成树

算法目的:给出V0,KV_{0},K和一个带边权的无向图,求出在V0V_{0}的度数最多为KK的限制下的最小生成树预备知识:最小生成树、动态规划定义:强制K度最小生成树为所有生成树中V0V_{0}的度...
  • commonc
  • commonc
  • 2017-01-16 16:55:29
  • 582

最小k度限制生成树

/************************************************* 算法引入: 最小k度限制生成树,就是指有特殊的某一点的度不能超过k时的最小生成树; 如果T是G的一...
  • Jarily
  • Jarily
  • 2013-04-09 20:48:29
  • 3291

poj1639:最小度限制生成树

题目:http://poj.org/problem?id=1639 题目大意: 所有的车要去同一地点,而此地点对车子有一个最大容量K,所以车子在行驶的过程中,可以相互合并,求所有车子到达目的地的距...
  • Davenny
  • Davenny
  • 2016-08-22 20:51:01
  • 93

最小度限制生成树 POJ1639

今天了解了一下最小度限制生成树。这个问题的本质依旧是生成树,但是对于某个点的度给定限制。也就是连到该点上的边不能超过限制的数量limit。 具体的解决过程和相关的证明可以看一下《最小生成树问题的扩展...
  • Hermit_Inwind
  • Hermit_Inwind
  • 2017-07-10 19:18:27
  • 119

[poj1639]度限制生成树

Problem DescriptionThe Contortion Brothers are a famous set of circus clowns, known worldwide for th...
  • aaron_1996
  • aaron_1996
  • 2016-08-28 23:14:51
  • 411

POJ1639 Picnic Planning 最小度限制生成树

Problem Address:http://poj.org/problem?id=1639 【前言】 一道10Y的题目,7WA+2RE。 刚开始确实不知道是这种东西。 后来看...
  • Human_CK
  • Human_CK
  • 2011-07-30 11:46:11
  • 463

算法合集之《最小生成树问题的拓展》.ppt

  • 2010年07月11日 10:45
  • 410KB
  • 下载

度限制最小生成树源码

  • 2009年10月08日 17:06
  • 4KB
  • 下载

最小度限制生成树

    把顶点V的度数度限制条件,把满足这一条件的生成树叫做度限制生成树,把权值和最小的度限制生成树称最小度限制生成树。    即求顶点V度数不超过K的最小生成树,令Hi 表示V的度数为 i 的最小生...
  • gzwzm
  • gzwzm
  • 2008-09-25 14:23:00
  • 1336
收藏助手
不良信息举报
您举报文章:poj1639最小度限制生成树(kruscal+邻接表)
举报原因:
原因补充:

(最多只允许输入30个字)