Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 8593 | Accepted: 4760 |
Description
You are assigned to design network connections between certain points in a wide area. You are given a set of points in the area, and a set of possible routes for the cables that may connect pairs of points. For each possible route between two points, you are given the length of the cable that is needed to connect the points over that route. Note that there may exist many possible routes between two given points. It is assumed that the given possible routes connect (directly or indirectly) each two points in the area.
Your task is to design the network for the area, so that there is a connection (direct or indirect) between every two points (i.e., all the points are interconnected, but not necessarily by a direct cable), and that the total length of the used cable is minimal.
Your task is to design the network for the area, so that there is a connection (direct or indirect) between every two points (i.e., all the points are interconnected, but not necessarily by a direct cable), and that the total length of the used cable is minimal.
Input
The input file consists of a number of data sets. Each data set defines one required network. The first line of the set contains two integers: the first defines the number P of the given points, and the second the number R of given routes between the points. The following R lines define the given routes between the points, each giving three integer numbers: the first two numbers identify the points, and the third gives the length of the route. The numbers are separated with white spaces. A data set giving only one number P=0 denotes the end of the input. The data sets are separated with an empty line.
The maximal number of points is 50. The maximal length of a given route is 100. The number of possible routes is unlimited. The nodes are identified with integers between 1 and P (inclusive). The routes between two points i and j may be given as i j or as j i.
The maximal number of points is 50. The maximal length of a given route is 100. The number of possible routes is unlimited. The nodes are identified with integers between 1 and P (inclusive). The routes between two points i and j may be given as i j or as j i.
Output
For each data set, print one number on a separate line that gives the total length of the cable used for the entire designed network.
Sample Input
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
Sample Output
0 17 16 26
Source
题意:
应该就是装宽带网络,给定节点和有权值的边的数目,问最小的成本是多少。
思路:
之前想的是,用一个标记数组记录节点的使用情况,但是总出现“内存错误”,
最后直接用克鲁斯卡尔算法的模板,就那样过了。。。对克鲁斯卡尔的理解还需要加强。
对于 prim 算法需要判断边的权值,因为有重边!
代码(克鲁斯卡尔):
412K 16MS
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int MYDD=1103;
int n,m;
int set[MYDD];
void init() {
for(int j=1; j<=n; j++)
set[j]=j;
}
int find(int x) {
int t,child=x;
while(x!=set[x])
x=set[x];
while(child!=x) {
t=set[child];// t 记录当前父节点
set[child]=x;
child=t;
}
return x;
}
bool combine(int x,int y) {//判断是否有同一个根节点
int fx=find(x);
int fy=find(y);
if(fx!=fy) {
set[fx]=fy;
return true;//不成环
}
return false;
}
struct EDGE {
int u,v,w;
} edge[MYDD*8];
bool cmp(EDGE x,EDGE y) {
return x.w<y.w;
}
int main() {
bool vis[MYDD];//记录节点的访问状态
while(scanf("%d",&n)&&n) {
init();
scanf("%d",&m);
for(int j=1; j<=m; j++) {
scanf("%d%d%d",&edge[j].u,&edge[j].v,&edge[j].w);
}
sort(edge+1,edge+m+1,cmp);
int count=0;//记录选择的边数
int ans=0;//记录生成树的权值
for(int j=1; count<n-1; j++) {//循环的终止条件可以选择节点数目 -1
if(combine(edge[j].u,edge[j].v)) {
count++;
ans+=edge[j].w;
}
}
printf("%d\n",ans);
}
return 0;
}
代码:
普里姆算法 5160KB 47ms 耗内存,也浪费时间,是不是需要优化
#include<stdio.h>
#include<string.h>
const int MYDD=1103;
const int INF=0x3f3f3f3f;
int map[MYDD][MYDD];
int vis[MYDD];//节点访问状态
int dis[MYDD];//节点到开始点的距离
int prim(int x) {//加入的节点数
int sum=0;//记录的生成树权值
memset(vis,0,sizeof(vis));
memset(dis,INF,sizeof(dis));
dis[1]=0;
for(int i=1; i<=x; i++) {
int k=-1,Tp=INF;
for(int j=1; j<=x; j++) {
if(!vis[j]&&dis[j]<Tp) {
k=j;//选择的节点编号,
Tp=dis[j];//临时变量记录最短路径
}
}
vis[k]=1;
for(int j=1; j<=x; j++) {
if(!vis[j]&&map[k][j]<dis[j])
dis[j]=map[k][j];
//更新未选中的点和已经连接的部分之间的最短距离
}
sum+=Tp;
}
return sum;
}
int main() {
int n,m;
while(scanf("%d",&n)&&n) {
memset(map,INF,sizeof(map));//地图初始化
scanf("%d",&m);
while(m--) {
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(map[u][v]>w||map[v][u]>w)//注意重边
map[u][v]=map[v][u]=w;//无向图
}
int ans=prim(n);
printf("%d\n",ans);
}
return 0;
}