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


相关文章推荐

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

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

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

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

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

Picnic PlanningTime Limit: 5000MS Memory Limit: 10000KTotal Submissions: 5846 Accepted: 1934Descript...

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

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

pku1639最小度限制生成树

题意:求图的最小生成树,不过其中一个点在最小生成树中的度要小于等于k。         分析:...

POJ 1639 度限制最小生成树Prim

题意:给出n条无向带权边,求所有点的最小生成树,其中“Park”的度数不超过最后输入的k,输入保证有解。 思路:思路其实很好理解,分为几个步骤: 1.当然将“Park”作为根节点,一开始先删掉它,则原...
  • dy0607
  • dy0607
  • 2016年10月12日 00:17
  • 216

[POJ 1639] 单度限制最小生成树

POJ 1639 Picnic Planning 单度限制最小生成树
  • SIOFive
  • SIOFive
  • 2014年04月10日 01:05
  • 916

POJ 1639 k度限制生成树

题意就是求最小生成树  但是有一个顶点的度必须不大于k 具体的方法网上都有,但是代码写起来之复杂难以令人想象,我由于代码能力还太弱,导致只能看着别人的代码重写一遍,优化了一些部分。 1.求出除...

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

题意: 给一个无向图连通图,求它的最小生成树,生成树满足条件点v0的度小于等于limit。 分析: 一般有度限制的最小生成树问题是np完全的,但单点度限制就比较简单了,先在原图上求不含v0的最小...
  • sepNINE
  • sepNINE
  • 2014年11月23日 10:25
  • 366

POJ1639 Picnic Planning(度限制生成树)

黑书上的例题,所以题意就不啰嗦了,具体模型是求一个无向图的最小生成树,其中有一个点的度有限制(假设为 k)。 要求最小 k 度生成树,我们可以按照下面的步骤来做: 设有度限制的点为 V0 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj1639最小度限制生成树(kruscal+邻接表)
举报原因:
原因补充:

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