HDU 1879 继续畅通工程 最小生成树
2016-04-02 17:15
423 查看
思路:
比较典型的求最小生成树,利用K算法或者P算法,如果在输入时两个村庄的修建状态为 已修建,那么我这里的做法是让他们之间的权值为 0,即修建费用为 0;然后套用算法就好了。
代码P算法:
代码K算法:
比较典型的求最小生成树,利用K算法或者P算法,如果在输入时两个村庄的修建状态为 已修建,那么我这里的做法是让他们之间的权值为 0,即修建费用为 0;然后套用算法就好了。
代码P算法:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <cctype> #include <algorithm> #include <queue> #include <stack> #include <map> #include <set> using namespace std; /* 集合之里:属于MST所构成的点集 反之亦然*/ const int MAXN = 103; const int INF = 0x3f3f3f3f; //最大值 int edge[MAXN][MAXN]; //邻接矩阵 int used[MAXN]; //标记这个点是否在最小生成树的集合里面 0 代表未加入 1 代表加入 int lowcost[MAXN]; //存放的是未被加入集合的 点 到 已经被加入集合的 点 的最短距离(如果集合里面的点和 多个集合之外的点相通 就取短的那个 这个数组伴随着加入点的变化而时刻变化着) int N; int prim(int start,int maxn) //假设 从 start 开始寻找MST, maxn 代表点的个数 { used[start] = 1; for(int i = 1; i <= maxn; i++) //刚开始只有start 这个点在集合里面 所以初始化这个数组为到集合之外的各个点的距离 ,如果没有则是无穷大(INF) { lowcost[i] = edge[start][i]; } int sumweight = 0; // MST 的权值 for(int i = 1; i <= maxn; i++) { int minn = INF ; //为找到最短的那条边 int v = -1; //标记找的那个点 for(int j = 1; j <= maxn; j++) //开始寻找集合之外得点到集合之里的点的最短边 { if(used[j] == 0 && lowcost[j] < minn) //在集合之外的点寻找最短的边 { minn = lowcost[j]; v = j; } } if(v != -1) //找到了 v 这个点 { used[v] = 1; //标记已被使用 sumweight += lowcost[v]; //更新权值 for(int j = 1; j <= maxn; j++) //更新存放最短边的集合 { if(used[j] == 0 && lowcost[j] > edge[v][j]) //在集合之外得点 寻找到集合之里各个点的最短边 更新数组 { lowcost[j] = edge[v][j]; } } } } return sumweight; } int main() { // freopen("in.cpp","r",stdin); while(cin >> N && N) { memset(edge, 0x3f, sizeof(edge)); //清空为最大值 memset(used, 0, sizeof(used)); //刚开始所有的点都在集合之外 int M = N * (N - 1) / 2; while(M--) { int u, v, w, ok; scanf("%d%d%d%d",&u,&v,&w,&ok); if(ok) w = 0; edge[u][v] = edge[v][u] = w; } cout << prim(1, N) << endl; } return 0; }
代码K算法:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <cctype> #include <algorithm> #include <queue> #include <stack> #include <map> #include <set> using namespace std; const int MAXN = 2e3+ 3; int pre[MAXN]; int n; int Find(int x) { return x == pre[x] ? x :(pre[x] = Find(pre[x])); } struct Node { int u, v, w; }cy[103 * 103]; int mycmp(Node a,Node b) { return a.w < b.w; } void mst() { for(int i = 0 ; i < 102; i++) pre[i] = i; } int kru() { int ans = 0; for(int i = 1; i <= n * (n - 1) / 2; i++) { int fv = Find(cy[i].v); int fu = Find(cy[i].u); if(fv != fu) { pre[fv] = fu; ans += cy[i].w; } } return ans; } int main() { //freopen("in.cpp","r",stdin); while(cin >> n && n) { mst(); for(int i = 1; i <= n * (n - 1) / 2; i++) { int u, v, w, ok; scanf("%d%d%d%d",&u,&v,&w,&ok); if(ok) w = 0; cy[i].u = u, cy[i].v = v, cy[i].w = w; } sort(cy + 1, cy + n * (n - 1) / 2 + 1, mycmp); int ans = kru(); printf("%d\n",ans); } return 0; }
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例
- PHP实现克鲁斯卡尔算法实例解析