hdoj/hdu 1233 还是畅通工程(最小生成树 Prim + 优先队列 实现)

 

超级传送门:

http://acm.hdu.edu.cn/showproblem.php?pid=1233

 

题目大意:

给出N个点之间的距离,要求建公路让N个点互相可达,求公路最短的长度。

 

题目分析:

由题目意思可得这一题是最小生成树的问题

 

下面用Prim + 优先队列 实现了一下,Prim + 优先队列 的大致想法是(我们要结合Prim来想):

 

Prim中有个dis[ ]的数组,点 v 到源点的距离,Prim + 优先队列 则是开一个结构体,其中两个属性 int v; //边端点 int w; //边权值 记录点 v 到源点的距离

然后用就可以优先队列在每一次循环找出 点v到源点最短的那条路径,加入最小生成树中,然后修改,把修改过的路径加入优先队列

代码实现如下:

 

#include<iostream>
#include<vector>
#include<queue>
using namespace std;

#define INFINITE 900000000

struct XEdge
{
    int v; //边端点
    int w; //边权值
    XEdge(int v_ = 0, int w_ = INFINITE):v(v_),w(w_) { }
};

//vector<int> pt;
vector< vector<XEdge> > G(500); //图的邻接表

bool operator <(const XEdge & e1, const XEdge & e2)
{
    return e1.w > e2.w;
}

int HeapPrim(const vector<vector<XEdge> > & G,  int n)
//G是邻接表,n是顶点数目,返回值是最小生成树权值和
{
    int i,j,k;
    XEdge xDist(1,0);
    priority_queue<XEdge> pq;
    vector<int> vDist(n+1); //各顶点到已经建好的那部分树的距离    vector<int> vUsed(n);//标记顶点是否已经被加入最小生成树
    vector<int> vUsed(n+1);//标记顶点是否已经被加入最小生成树
    int nDoneNum = 0; //已经被加入最小生成树的顶点数目
    for( i = 0;i <= n;i ++ ) {
        vUsed[i] = 0;
        vDist[i] = INFINITE;
    }
    nDoneNum = 0;
    int nTotalW = 0;
    pq.push(XEdge(1,0));
    while( nDoneNum < n && !pq.empty() ) { 
        do {
            xDist = pq.top();       pq.pop();
        } while( vUsed[xDist.v] == 1 && ! pq.empty()); 
        if( vUsed[xDist.v] == 0 ) {
            nTotalW += xDist.w;    vUsed[xDist.v] = 1;  nDoneNum ++;
            for( i = 0;i < G[xDist.v].size();i ++ ) {
                int k = G[xDist.v][i].v;
                if( vUsed[k] == 0) {
                    int w = G[xDist.v][i].w ;    
                    if( vDist[k] > w ) {
                        vDist[k] = w;
                        pq.push(XEdge(k,w));
                    }
                }
            }
        }
    }
    if( nDoneNum < n )
        return -1; //图不连通
    return nTotalW;
}


int main()
{
    int N;
    int temp;
    int i,j;
    int a,b,l;
    int sum;
    while(scanf("%d",&N) != EOF)
    {
        if(N == 0) break;
        temp = N*(N-1)/2;
        for(i=0;i<temp;i++)
        {
            scanf("%d %d %d",&a,&b,&l);
            G[a].push_back(XEdge(b,l));    
            G[b].push_back(XEdge(a,l));
        }
        sum  = HeapPrim(G,N);
        printf("%d\n",sum);
        /*for (i=0;i<500;i++)
        {
            G[i].clear();
        }*/
        G.clear();
        G.resize(500);
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值