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;
}


最小生成树(MST)—prim和kruskal算法

最小生成树(MST:minimum-cost spanning tree) 也称最小支撑树,任何只由G的边构成,并包含G的所有顶点的树称为G的生成树(G连通).加权无向图G的生成树的代价是该生成树的...
  • u010025211
  • u010025211
  • 2015年07月11日 22:41
  • 1400

图的邻接表(广度优先遍历,深度优先遍历,最小生成树(Kruskal算法))

main.h: #include #include #define DefaultSize 10 #define maxWeight -1 using namespace std; tem...
  • liuhuiyan_2014
  • liuhuiyan_2014
  • 2015年04月20日 12:50
  • 1126

Kruskal算法求图的最小生成树的完整C代码

求加权连通图的最小生成树的算法。kruskal算法总共选择n- 1条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合中。注意到所选取的边若产生环路则不可能...
  • u014488381
  • u014488381
  • 2014年11月24日 16:41
  • 8167

POJ 1639:Picnic Planning(最小度限制生成树)

Picnic Planning Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 7356  ...
  • wugj03
  • wugj03
  • 2012年04月18日 12:34
  • 827

P300-野餐计划(POJ-1639最小度限制生成树)

黑书上的例题,具体模型是求一个无向图的最小生成树,其中有一个点的度有限制(假设为 k)。   要求最小 k 度生成树,我们可以按照下面的步骤来做: 设有度限制的点为 V0 ,V0称为根节点 1...
  • famousDT
  • famousDT
  • 2011年12月20日 10:20
  • 594

最小度限制生成树 POJ1639

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

POJ 1639 Picnic Planning(初遇最小度限制生成树)

这是最小度限制生成树的经典问题,题意就不说了 题目链接:http://poj.org/problem?id=1639 一般都是1个顶点的度有限制k,如果每个顶点的度都有限制,那么当前是NP难的。 为了...
  • kalilili
  • kalilili
  • 2015年02月11日 20:56
  • 664

poj 1639 Picnic Planning 最小K度限制生成树

Picnic PlanningTime Limit: 5000MS Memory Limit: 10000KTotal Submissions: 5846 Accepted: 1934Descript...
  • kongming_acm
  • kongming_acm
  • 2011年03月26日 21:11
  • 501

poj1639 Picnic Planning 最小度数限制生成树

题意:若干个人开车要去park聚会,但是park能停的车是有限的,为k。所以这些人要通过先开车到其他人家中,停车,然后拼车去聚会。另外,车的容量是无限的,他们家停车位也是无限的。求开车总行程最短。 ...
  • u012749539
  • u012749539
  • 2014年07月22日 23:10
  • 1006

pku1639最小度限制生成树

题意:求图的最小生成树,不过其中一个点在最小生成树中的度要小于等于k。         分析:...
  • ahero_happy
  • ahero_happy
  • 2011年08月11日 11:55
  • 635
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj1639最小度限制生成树(kruscal+邻接表)
举报原因:
原因补充:

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