题目链接 :http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2144
图结构练习——最小生成树
Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述
有n个城市,其中有些城市之间可以修建公路,修建不同的公路费用是不同的。现在我们想知道,最少花多少钱修公路可以将所有的城市连在一起,使在任意一城市出发,可以到达其他任意的城市。
输入
输入包含多组数据,格式如下。
第一行包括两个整数n m,代表城市个数和可以修建的公路个数。(n <= 100, m <=10000)
剩下m行每行3个正整数a b c,代表城市a 和城市b之间可以修建一条公路,代价为c。
输出
每组输出占一行,仅输出最小花费。
示例输入
3 2 1 2 1 1 3 1 1 0
示例输出
2 0
提示
来源
赵利强
示例程序
由于n*n和m的大小差不多,所以这题可以选择Prime算法(n*n<m),也可以选择Kruskal(n*n>m)
先是Prime算法,代码如下
view plaincopyprint如果您复制代码时出现行号,请点击左边的“view
plain”后再复制
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #define inf 99999999
- using namespace std;
- int main()
- {
- int n, m;
- while(~scanf("%d %d", &n, &m))
- {
- int a[100+5][100+5];
- for(int i=1;i<=n;i++)
//初始化 - for(int j=1;j<=n;j++)
- if(i==j) a[i][j]=0;
- else a[i][j]=inf;
- while(m--)
- {
- int u, v, w;
- scanf("%d %d %d", &u, &v, &w);
- if(a[u][v]>w) a[u][v]=a[v][u]=w;
//注意这里是无向图,并且可能存在重复的u、v信息 - }
- int dis[100+5], sum=0;
- bool vis[100+5];
- for(int i=1;i<=n;i++)
- dis[i]=a[1][i];
- memset(vis,0,sizeof(vis));
//设置标记数组vis - vis[1]=1;
- for(int i=1;i<n;i++)
- {
- int min=inf, pos=inf;
- for(int j=1;j<=n;j++)
- if(!vis[j]&&dis[j]<min)
//查找并记录最小值及其下标,表明此值已经“明确”为最短(意思是没有其他路径可以让它变得更短,也就是无法再进行“松弛”) - {
- min=dis[j];
- pos=j;
- }
- if(min>=inf) break;
//如果所有值都已“明确”为最短,结束循环 - sum+=min;
- vis[pos]=1;
- for(int j=1;j<=n;j++)
- if(!vis[j]&&dis[j]>a[pos][j])
//使用该最短路径“松弛”其他路径 - dis[j]=a[pos][j];
- }
- printf("%d\n", sum);
- }
- return 0;
- }
再是Kruskal:
view plaincopyprint如果您复制代码时出现行号,请点击左边的“view
plain”后再复制
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- using namespace std;
- int pre[100+5];
- struct node
- {
- int u, v, w;
- }boy[10000+5];
- bool cmp(node a, node b)
- {
- return a.w<b.w;
- }
- int root(int a)
\\查找 - {
- int x=a;
- while(x!=pre[x])
- {
- x=pre[x];
- }
- while(a!=x)
//路径压缩 - {
- pre[a]=x;
- a=pre[a];
- }
- return x;
- }
- int main()
- {
- int m, n;
- while(~scanf("%d %d", &n, &m))
- {
- for(int i=1;i<=n;i++)
- pre[i]=i;
- for(int i=0;i<m;i++)
- scanf("%d %d %d", &boy[i].u, &boy[i].v, &boy[i].w);
- sort(boy,boy+m,cmp); //对结构体按路径花费进行升序排序
- int ans=0, cnt=0;
- for(int i=0;i<m;i++)
- {
- if(root(boy[i].u)!=root(boy[i].v))
//合并 - {
- pre[root(boy[i].u)]=root(boy[i].v);
- ans+=boy[i].w;
- cnt++;
- }
- if(cnt>=n-1) break;
//只需再联通n-1个节点即可保证全部联通 - }
- printf("%d\n", ans);
- }
- return 0;
- }
十一点半了快,睡觉了,明天继续,晚安世界
时间: 2024-11-13 09:35:45