HNACM(八)D-引水工程
2016-04-08 17:35
357 查看
传送门
最小生成树算法
首先找到一个自建水库最少费用的 然后以此为根本 找到与之相关的边
还要注意当权值相等时的处理方法
另一种方法,把自建费用当成结点0到结点i的费用,然后用最下生成树算法
感谢@Dart 提供思路
最小生成树算法
首先找到一个自建水库最少费用的 然后以此为根本 找到与之相关的边
还要注意当权值相等时的处理方法
#include <bits/stdc++.h> #define N 310 #define ll long long #define MAX 11111 using namespace std; int n, w , p , water ; //w 是 每个地方自建水库所需的费用 //water 是存放已经解决用水问题的地方 bool vis ; int prim(int pos, int sum){ int i, j, k, cur = 0; memset(vis, false, sizeof(vis)); memset(water, 0, sizeof(water)); water[cur++] = pos; vis[pos] = true; while(cur < n){ int mindist = MAX; int min1 = MAX; int u = -1; for (i = 0; i < cur; i++){//遍历所有的已经解决用水问题的点 for (j = 0; j < n; j++){ if (!vis[j] && j != water[i]){ if (mindist > p[water[i]][j]){ //未解决问的点,找出从其他地方引水的最小费用 mindist = p[water[i]][j]; min1 = w[j]; u = j; }else if (mindist == p[water[i]][j] && min1 > w[j]){//如果当前最小值和权值相等,比较自建费用 min1 = w[j]; u = j; } } } } vis[u] = true; water[cur++] = u; sum += min(min1, mindist);//去自建费用和从其他地方引水的费用的较小者 } return sum; } int main(){ #ifndef ONLINE_JUDGE // freopen("1.txt", "r", stdin); // freopen("d.in", "r", stdin); // freopen("d1.out", "w", stdout); #endif int i, j, k, K, Min, pos; scanf("%d", &K); while(K--){ scanf("%d", &n); Min = MAX; for (i = 0; i < n; i++){ scanf("%d", &w[i]); if (Min > w[i]){//先寻找自建水库的费用最小的地方 pos = i; Min = w[i]; } } for (i = 0; i < n; i++){ for (j = 0; j < n; j++){ scanf("%d", &p[i][j]); } } printf("%d\n", prim(pos, Min));//先从自建水库最小的地方开始 } return 0; }
另一种方法,把自建费用当成结点0到结点i的费用,然后用最下生成树算法
感谢@Dart 提供思路
#include <iostream> #include <cstdio> #define MAXN 310 using namespace std; int g[MAXN][MAXN], dis[MAXN]; bool vis[MAXN]; const int INF = 0x3f3f3f3f; int n; int prim(int st){ int i, j, k; for (i = 0; i <= n; i++){ vis[i] = false; dis[i] = g[st][i]; } dis[st] = 0; vis[st] = true; int sum = 0; for (i = 1; i <= n; i++){ int Min = INF; int v = -1; for (j = 0; j <= n; j++){ if (!vis[j] && Min > dis[j]){ v = j; Min = dis[j]; } } vis[v] = true; sum += Min; for (j = 0; j <= n; j++){ if (!vis[j] && g[v][j] < dis[j]){ dis[j] = g[v][j]; } } } return sum; } int main(){ int i, j, k, T; scanf("%d", &T); while(T--){ scanf("%d", &n); for (i = 1; i <= n; i++){ scanf("%d", &g[0][i]); g[i][0] = g[0][i]; } for (i = 1; i <= n; i++){ for (j = 1; j <= n; j++){ scanf("%d", &g[i][j]); } } printf("%d\n", prim(0)); } return 0; }
相关文章推荐
- 学习笔记之linux内存分配读书笔记
- Android Webview upload 图片上传
- APP架构师必看:面对爆发流量如何进行架构调整
- MySQL的btree索引和hash索引的区别
- [转]常识:输入网址之后发生了什么(常识,但是谁又能说明白呢?)
- readonly const
- 【LeetCode-45】Jump Game II
- 事务四大特性详解
- UVa 301 - Transportation
- 学习笔记之被老师问倒的问题
- 【JQuery】表单验证插件——validate
- IOS打包封装Framework
- 【学习笔记----数据结构05-栈与队列】
- Struts2的properties文件
- WEB前端常见面试题汇总
- 发布一个关于SharePoint的管理小工具
- Logstash1.5 发邮件报警
- MongoDB学习 (六):查询
- c3p0源码解析 四 (C3P0Config类)
- 学习笔记之智能指针简单理解