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

一、.思路

设限制结点为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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1) { JOptionPane.showMessageDialog(this, "请选择要删除的图书!", "提示", JOptionPane.WARNING_MESSAGE); } else { 这是一道经典的最短路问题,可以使用Dijkstra算法或者Floyd算法来解决。 D String bookId = bookInfoTable.getValueAt(selectedRow, 0).toString(); int option = JOptionPane.showConfirmDialog(this, "确定要删除编号为 " + bookId + " 的图书吗?", "提示", JOptionPane.YES_NO_OPTION); if (optionijkstra算法的基本思想是从起点开始,依次遍历所有节点,每次选择距离起点最 == JOptionPane.YES_OPTION) { deleteBookInfo(bookId); loadBookInfo(); } } } else if (e.getSource() == backButton) { new MainFrame(); setVisible(false); } } private void loadBookInfo() { 近的节点进行松弛操作,直到到达终点或者所有节点都被遍历完。 Floyd算法则 tableModel.setRowCount(0); Connection conn = null; Statement stmt = null; ResultSet rs = null; try { 是通过动态规划求解所有节点之间的最短路径。具体来说,利用一个二维数组存 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/book_management?useSSL=false&serverTimezone=UTC", "root", "root"); stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT * FROM book_info"); while (rs.next())储任意两个节点之间的最短距离,然后依次考虑增加中间节点,更新所有节点 { Object[] rowData = new Object[6]; rowData[0] = rs.getInt("book_id"); rowData[1]之间的距离,直到所有节点都被考虑过。 无论使用哪种算法,都需要先构建 = rs.getString("book_name"); rowData[2] = rs.getString("author"); rowData[3] = rs.getString("publisher"); rowData[4] = rs.getDouble("price"); rowData[5] = rs.getInt("quantity"); tableModel.addRow(row出图的邻接矩阵或邻接表,然后根据算法的要求进行处理即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值