HDU1102 - Constructing Roads 用优先队列优化Prim最小生成树

来源:互联网 发布:金百福珠宝软件试用版 编辑:程序博客网 时间:2024/05/20 23:36

HDU1102 - Constructing Roads : http://acm.hdu.edu.cn/showproblem.php?pid=1102

题意 : 给你N个村庄,接下来是N行输入,第 i 行的第 j 个数字代表的是编号为 i 的村庄到编号为j的村庄的距离.例如 : 0  2  5. 表示村庄1到自己的距离为0,到村庄2的距离为2,到村庄3的距离是5,N行输入后又有Q行输入,每行两个整数x, y.表示x和y之间已经修好路了.问要将所有村庄连在一起,最少要修多长的公路.

思路 : 就是用最小生成树求解,,,,,,Prim + 优先队列 可节省时间.

代码 :

#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;const int MAXN = 111;const int Inf = 1<<30;int Map[MAXN][MAXN],Vis[MAXN],Dist[MAXN],Ans;int N,Q;int x,y;void Initial(){Ans = 0;fill(Vis,Vis + MAXN,0);fill(Dist,Dist + MAXN,Inf);}struct Node{int v,len;//v是编号,len是v到目标集合的距离(将所有已经连在一起的村庄看成一个集合)bool friend operator <(Node x,Node y)//用优先队列取出距离 已经连好的村庄 最近的村庄编号 {return x.len > y.len;}};void Prim(){priority_queue<Node>Edge;Node Now;Now.v = 1,Now.len = 0;//假设先从第一个村庄开始,从其他的编号开始也可以,但是 len一定是 0 Edge.push(Now);while(!Edge.empty()){Now = Edge.top();Edge.pop();if(Vis[Now.v])continue;//已经在集合里,不再访问 Vis[Now.v] = 1;//否则标记为访问Ans += Now.len;//同时把当前节点 v到目标集合的距离len加到答案里,优先队列里取出来的可以保证是最短的路for(int i = 1;i <= N;i++){if(!Vis[i] && Map[Now.v][i] < Dist[i])//满足此条件则可以加入队列 {Node Next;Next.v = i;Next.len = Dist[i] = Map[Now.v][i];Edge.push(Next); }}}printf("%d\n",Ans);}int main(){while(~scanf("%d",&N)){Initial();for(int i = 1;i <= N;i++)for(int j = 1;j <= N;j++)scanf("%d",&Map[i][j]);scanf("%d",&Q);while(Q--){scanf("%d%d",&x,&y);//x,y已经相连 Map[x][y] = Map[y][x] = 0;}Prim();}return 0;} 


0 0
原创粉丝点击