hihoCoder_#1109_堆优化的Prim算法

来源:互联网 发布:mac移动硬盘不能写入 编辑:程序博客网 时间:2024/06/06 12:28

#1109 : 最小生成树三·堆优化的Prim算法

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

回到两个星期之前,在成功的使用Kruscal算法解决了问题之后,小Ho产生了一个疑问,究竟这样的算法在稀疏图上比Prim优化之处在哪里呢?

提示:没有无缘无故的优化!

输入

每个测试点(输入文件)有且仅有一组测试数据。

在一组测试数据中:

第1行为2个整数N、M,表示小Hi拥有的城市数量和小Hi筛选出路线的条数。

接下来的M行,每行描述一条路线,其中第i行为3个整数N1_i, N2_i, V_i,分别表示这条路线的两个端点和在这条路线上建造道路的费用。

对于100%的数据,满足N<=10^5, M<=10^6,于任意i满足1<=N1_i, N2_i<=N, N1_i≠N2_i, 1<=V_i<=10^3.

对于100%的数据,满足一定存在一种方案,使得任意两座城市都可以互相到达。

输出

对于每组测试数据,输出1个整数Ans,表示为了使任意两座城市都可以通过所建造的道路互相到达至少需要的建造费用。

样例输入
5 291 2 6742 3 2493 4 6724 5 9331 2 7883 4 1472 4 5043 4 381 3 653 5 61 5 8651 3 5901 4 6822 4 2272 4 6361 4 3121 3 1432 5 1582 3 5163 5 1021 5 6051 4 994 5 2242 4 1983 5 8941 5 8453 4 72 4 141 4 185
样例输出

92

分析:在稀疏图中,利用最小堆维护所取得的边。其实就是用小根堆维护一个与1号节点相连的边的集合,然后每次在其中找出最小的边,而将这条边连接的点加入到1号节点中,其实就是用新加入节点连接出的几条边去更新堆。

题目链接:http://hihocoder.com/problemset/problem/1109

代码清单:

#include<map>#include<queue>#include<stack>#include<cmath>#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int maxn = 100000 + 5;const int maxv = 1000000 + 5;struct Edge{    int to;    int dis;    Edge(int to,int dis){        this -> to = to;        this -> dis = dis;    }    friend bool operator<(Edge a,Edge b){        return a.dis>b.dis;    }};int N,M,a,b,c;vector<Edge>graph[maxn];priority_queue<Edge>q;bool vis[maxn];void init(){    while(!q.empty()) q.pop();    for(int i=0;i<maxn;i++) graph[i].clear();    memset(vis,false,sizeof(vis));}void input(){    scanf("%d%d",&N,&M);    for(int i=0;i<M;i++){        scanf("%d%d%d",&a,&b,&c);        graph[a].push_back(Edge(b,c));        graph[b].push_back(Edge(a,c));    }}int queue_prim(){    for(int i=0;i<graph[1].size();i++){        q.push(graph[1][i]);    }    vis[1]=true;    int left=N-1;    int sum=0;    while(!q.empty()&&left){        Edge e=q.top(); q.pop();        if(vis[e.to]) continue;        sum+=e.dis;        left--;        vis[e.to]=true;        for(int i=0;i<graph[e.to].size();i++){            Edge t=graph[e.to][i];            if(!vis[t.to]) q.push(t);        }    }return sum;}void solve(){    printf("%d\n",queue_prim());}int main(){    init();    input();    solve();    return 0;}

prim算法(与本题无关):

#include<map>#include<queue>#include<stack>#include<cmath>#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int maxn = 1000 + 5;const int max_dis = 1e9 + 5;int n;int graph[maxn][maxn];int dis[maxn];bool vis[maxn];void init(){    fill(dis,dis+n,max_dis);    memset(vis,false,sizeof(vis));}void input(){    scanf("%d",&n);    for(int i=0;i<n;i++)        for(int j=0;j<n;j++)        scanf("%d",&graph[i][j]);}int prim(){    init();    dis[0]=0;    int sum=0;    while(true){        int v=-1;        for(int i=0;i<n;i++){            if(!vis[i] &&(v==-1 || dis[i]<dis[v]))                v=i;        }        if(v==-1) break;        sum+=dis[v];        vis[v]=true;        for(int i=0;i<n;i++){            dis[i]=min(dis[i],graph[v][i]);        }    }return sum;}void solve(){    printf("%d\n",prim());}int main(){    input();    solve();    return 0;}


0 0