首页 > 代码库 > HDU 1102 Constructing Roads, Prim+优先队列
HDU 1102 Constructing Roads, Prim+优先队列
题目链接:HDU 1102 Constructing Roads
Constructing Roads
Problem Description
There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected.
We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.
We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.
Input
The first line is an integer N (3 <= N <= 100), which is the number of villages. Then come N lines, the i-th of which contains N integers, and the j-th of these N integers is the distance (the distance should be an integer within [1, 1000]) between village i and village j.
Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.
Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.
Output
You should output a line contains an integer, which is the length of all the roads to be built such that all the villages are connected, and this value is minimum.
Sample Input
3 0 990 692 990 0 179 692 179 0 1 1 2
Sample Output
179
Source
kicc
Recommend
Eddy | We have carefully selected several similar problems for you: 1142 1598 1116 1269 1596
题意
有N个村子要修道路,给出了修每条道路的原始费用,现在有的道路已经修好了。我们要求的是修剩下的道路的最小费用。
分析
最小生成树算法,因为是邻接矩阵,因而使用Prim方法非常方便求解,对于已经修好的道路,我们可以将他们的费用设置为0,再用Prim算法求解即可得到。
代码
邻接矩阵:
#include <iostream> #include <cstdio> #include <queue> using namespace std; #define maxn 110 #define INF 0xffff int g[maxn][maxn]; int n; struct node { int v, key; friend bool operator<(node a, node b) { return a.key > b.key; } }; bool visited[maxn]; node vx[maxn]; priority_queue<node> q; void Prim() { for(int i = 1; i <= n; i++) { vx[i].v = i; vx[i].key = INF; visited[i] = false; } vx[1].key = 0; q.push(vx[1]); while(!q.empty()) { node nd = q.top(); q.pop(); int st = nd.v; if(visited[st]) continue; visited[st] = true; for(int j = 1; j <= n; j++) { if(j != st && !visited[j] && vx[j].key > g[st][j]) { vx[j].key = g[st][j]; q.push(vx[j]); } } } } int main() { int m, a, b; while(~scanf("%d", &n)) { for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) scanf("%d", &g[i][j]); g[i][i] = INF; } scanf("%d", &m); while(m--) { scanf("%d%d", &a, &b); g[a][b] = g[b][a] = 0; } Prim(); int ans = 0; for(int i = 1; i <= n; i++) ans += vx[i].key; printf("%d\n", ans); } return 0; }
邻接表:
#include <iostream> #include <cstdio> #include <vector> #include <queue> using namespace std; #define maxn 110 //最大顶点个数 int n, m; //顶点数,边数 struct arcnode //边结点 { int vertex; //与表头结点相邻的顶点编号 int weight; //连接两顶点的边的权值 arcnode * next; //指向下一相邻接点 arcnode() {} arcnode(int v,int w):vertex(v),weight(w),next(NULL) {} }; struct vernode //顶点结点,为每一条邻接表的表头结点 { int vex; //当前定点编号 arcnode * firarc; //与该顶点相连的第一个顶点组成的边 }Ver[maxn]; void Init() //建立图的邻接表需要先初始化,建立顶点结点 { for(int i = 1; i <= n; i++) { Ver[i].vex = i; Ver[i].firarc = NULL; } } void Insert(int a, int b, int w) //尾插法,插入以a为起点,b为终点,权为w的边,效率不如头插,但是可以去重边 { arcnode * q = new arcnode(b, w); if(Ver[a].firarc == NULL) Ver[a].firarc = q; else { arcnode * p = Ver[a].firarc; if(p->vertex == b) { if(p->weight > w) p->weight = w; return ; } while(p->next != NULL) { if(p->next->vertex == b) { if(p->next->weight > w); p->next->weight = w; return ; } p = p->next; } p->next = q; } } void Insert2(int a, int b, int w) //头插法,效率更高,但不能去重边 { arcnode * q = new arcnode(b, w); if(Ver[a].firarc == NULL) Ver[a].firarc = q; else { arcnode * p = Ver[a].firarc; q->next = p; Ver[a].firarc = q; } } struct node //保存key值的结点 { int v; int key; friend bool operator<(node a, node b) //自定义优先级,key小的优先 { return a.key > b.key; } }; #define INF 0xfffff //权值上限 bool visited[maxn]; //是否已经加入树 node vx[maxn]; //保存每个结点与其父节点连接边的权值 priority_queue<node> q; //优先队列stl实现 void Prim() //s表示根结点 { for(int i = 1; i <= n; i++) //初始化 { vx[i].v = i; vx[i].key = INF; visited[i] = false; } vx[1].key = 0; q.push(vx[1]); while(!q.empty()) { node nd = q.top(); //取队首,记得赶紧pop掉 q.pop(); if(visited[nd.v]) //注意这一句的深意,避免很多不必要的操作 continue; visited[nd.v] = true; arcnode * p = Ver[nd.v].firarc; while(p != NULL) //找到所有相邻结点,若未访问,则入队列 { if(!visited[p->vertex] && p->weight < vx[p->vertex].key) { vx[p->vertex].key = p->weight; vx[p->vertex].v = p->vertex; q.push(vx[p->vertex]); } p = p->next; } } } int main() { int m, a, b, x; while(~scanf("%d", &n)) { Init(); for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { scanf("%d", &x); if(x != 0) Insert2(i, j, x); } } scanf("%d", &m); while(m--) { scanf("%d%d", &a, &b); Insert(a, b, 0); Insert(b, a, 0); } Prim(); int ans = 0; for(int i = 1; i <= n; i++) ans += vx[i].key; printf("%d\n", ans); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。