专题六 最小生成树
- POJ 1251 Jungle Roads
- POJ 1287 Networking
- POJ 2031 Building a Space Station
- POJ 2421 Constructing Roads
- ZOJ 1586 QS Network
- POJ 1789 Truck History
- POJ 2349 Arctic Network
- POJ 1751 Highways
- POJ 1258 Agri-Net
- POJ 3026 Borg Maze
- POJ 1679 The Unique MST
- HDU 1233 还是畅通工程
- HDU 1301 Jungle Roads
- HDU 1875 畅通工程再续
POJ 1251 Jungle Roads
描述
热带岛屿Lagrishan的头长老有问题。几年前,在村庄之间的额外道路上花了一大笔外援资金。但丛林无情地超越了道路,因此大型公路网络的维护成本太高。长老理事会必须选择停止维持一些道路。左上方的地图显示了现在使用的所有道路以及维护它们的每月aacms的成本。当然,即使路线不像以前那么短,也需要在维护道路上的所有村庄之间进行某种方式。首席长老想告诉长老会,他们每月可以花费最少的金额来维持连接所有村庄的道路。在上面的地图中,村庄标有A到I. 右边的地图显示了最便宜的道路,每月216个aacms。你的任务是编写一个可以解决这些问题的程序。
输入
输入由1到100个数据集组成,后面跟着一个只包含0的最后一行。每个数据集都以一个只包含数字n的行开头,这个数字是村庄的数量,1 <n <27,村庄被标记使用字母表的前n个字母,大写。每个数据集都以n-1行完成,这些行以字母顺序从村庄标签开始。最后一个村庄没有线路。村庄的每条线路都以村庄标签开头,后面跟着一个从这个村庄到村庄的道路数k,后面有字母标签。如果k大于0,则该线继续每条k条道路的数据。每条道路的数据是道路另一端的村庄标签,后面是道路的aacms的每月维护费用。维护成本将是小于100的正整数。行中的所有数据字段由单个空格分隔。道路网络将始终允许所有村庄之间的旅行。该网络永远不会有超过75条道路。没有村庄将有超过15条道路通往其他村庄(在字母表之前或之后)。在下面的示例输入中,第一个数据集与上面的地图一起使用。
产量
每个数据集的输出为每行一个整数:维持连接所有村庄的道路系统的每月aacms的最低成本。注意:检查每一组可能的道路的强力解决方案将无法在一分钟的时间内完成。
样本输入
9
A 2 B 12 I 25
B 3 C 10 H 40 I 8
C 2 D 18 G 55
D 1 E 44
E 2 F 60 G 38
F 0
G 1 H 35
H 1 I 35
3
A 2 B 10 C 40
B 1 C 20
0
样本输出
216
30
资源
这题比较难的地方在于输入把,和常规的建图不一样,给出了字母作为编号,给边的方式也略有不同
bool operator < (const edge &e) const{//c++自定义比较
return w>e.w;//小
}
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n,m,k,w,ans;
int f[50];
struct edge{
int a,b,w;
bool operator < (const edge &e) const{
return w>e.w;//小
}
};
bool cmp(edge a,edge b){
return a.w < b.w;
}
int find(int x){
if(f[x]==x)
return x;
return f[x] = find(f[x]);
}
void Union(int x,int y,int w){
int a = find(x);
int b = find(y);
if(a!=b){
f[a] = b;
ans+=w;
}
}
int main(){
while(~scanf("%d",&n),n){
m = n-1;
char str;
priority_queue<edge> pq;
ans = 0;
for(int i=0;i<=n;i++)
f[i] = i;
while(m--){
cin>>str>>k;
char str1;
while(k--){
cin>>str1>>w;
edge e;
e.a = (str-'A');
e.b = (str1-'A');
e.w = w;
pq.push(e);
}
}
while(!pq.empty()){
edge u = pq.top();
pq.pop();
// cout<<u.a<<" "<<u.b<<" "<<u.w<<"!!!"<<endl;
Union(u.a,u.b,u.w);
}
cout<<ans<<endl;
}
return 0;
}
POJ 1287 Networking
输出
您被分配设计广泛区域中某些点之间的网络连接。您将获得该区域中的一组点,以及可连接成对点的电缆的一组可能路线。对于两点之间的每条可能路线,您将获得连接该路线上的点所需的电缆长度。请注意,两个给定点之间可能存在许多可能的路径。假设给定的可能路线(直接或间接)连接该区域中的每两个点。
您的任务是为该区域设计网络,以便在每两个点之间存在连接(直接或间接)(即,所有点都是互连的,但不一定是通过直接电缆),并且总长度为用过的电缆很小。
输入
输入文件由许多数据集组成。每个数据集定义一个必需的网络。集合的第一行包含两个整数:第一行定义给定点的数量P,第二行定义点之间给定路径的数量R. 以下R行定义了点之间的给定路线,每条线给出三个整数:前两个数字标识点,第三个给出路线的长度。数字用空格分隔。仅给出一个数字P = 0的数据集表示输入的结束。数据集用空行分隔。
最大点数为50.给定路线的最大长度为100.可能的路线数量不受限制。节点用1和P(含)之间的整数标识。两个点i和j之间的路线可以给出为ij或j i。
产量
对于每个数据集,在单独的行上打印一个数字,该行显示用于整个设计网络的电缆的总长度。
样本输入
1 0
2 3
1 2 37
2 1 17
1 2 68
3 7
1 2 19
2 3 11
3 1 7
1 3 5
2 3 89
3 1 91
1 2 32
5 7
1 2 5
2 3 7
2 4 8
4 5 11
3 5 10
1 5 6
4 2 12
0
样本输出
0
17
16
26
资源
优先队列+并查集
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
int n,m,ans=0;
int f[105];
struct edge{
int u,v,w;
bool operator < (const edge &e) const{
return w>e.w;//小
}
};
int find(int x){
if(f[x]==x)
return x;
return f[x] = find(f[x]);
}
void Union(int x,int y,int w){
int a = find(x);
int b = find(y);
if(a!=b){
f[a] = b;
ans += w;
}
}
int main(){
while(~scanf("%d",&n),n){
scanf("%d",&m);
priority_queue<edge> pq;
ans = 0;
for(int i=0;i<=n;i++)
f[i] = i;
while(m--){
edge e;
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
e.u = a;
e.v = b;
e.w = c;
pq.push(e);
}
while(!pq.empty()){
edge e = pq.top();
pq.pop();
Union(e.u,e.v,e.w);//还有个小优化就是最小生成树建成就break
}
printf("%d\n",ans);
}
return 0;
}