POJ 1679 次小生成树 Kruskal +DFS优化
2015-07-28 16:41
357 查看
http://poj.org/problem?id=1679
看了网上大部分都是直接多次跑 kruskal的,数据大了会耗时间。先深搜一次跑出最小生成树各点路径的最大边权,存在MAXCST[I][J]表示i——》J的路径最大的边的边权
然后逐一减去这个边加上不是最小生成树的边再取最小值便是次小生成树了
看了网上大部分都是直接多次跑 kruskal的,数据大了会耗时间。先深搜一次跑出最小生成树各点路径的最大边权,存在MAXCST[I][J]表示i——》J的路径最大的边的边权
然后逐一减去这个边加上不是最小生成树的边再取最小值便是次小生成树了
#include<iostream> #include<vector> #include<algorithm> using namespace std; int father[105];//父亲节点数组 bool used[10005];//标记边是否处于最小生成树内 int cost[105][105];//记录最小生成树2点的花费 int maxcost[105][105];//存最小生成树任意2点的最大路径 bool mark[105];//最小生成树标记 vector<int> vis;//记录哪些点在最小生成树内 int ans;//最小生成树的权值之和 int n, m; bool hash1[105]; struct node { int from, to, w; }; bool cmp(node &a,node &b) { if (a.w<b.w) return true; return false; } node edug[10005]; vector<int> shu[105]; void init() { memset(mark, false, sizeof(mark)); memset(used, false, sizeof(used)); memset(maxcost, -1, sizeof(maxcost)); memset(cost, -1, sizeof(cost)); for (int i = 0; i <= n; i++) { father[i] = i; } ans = 0; vis.clear(); } int find(int x) { if (father[x] == x) return x; return father[x] = find(father[x]); } bool combine(int x,int y,int w,int i) { int fx = find(x); int fy = find(y); if (fx != fy) { used[i] = true; father[fy] = fx; shu[x].push_back(y);//建立最小生成树的领接表,这里是无向变 shu[y].push_back(x); ans+=cost[x][y] = cost[y][x] = w;//统计和记录最小生成树2点花费 if (!mark[x])//记录哪些点在最小生成树内 { mark[x] = true; vis.push_back(x); } if (!mark[y]) { mark[y] = true; vis.push_back(y); } return true; } return false; } void dfs(int f, int t, int w, int root)//深搜处理最小树的任意2点的最大路径 { if (hash1[f])//找过了 return; hash1[f] = true; for (int i = 0; i < shu[f].size(); i++) { if (shu[f][i] == t) continue; maxcost[root][shu[f][i]] = maxcost[shu[f][i]][root] = max(w, cost[f][shu[f][i]]);//以前走过的路径和当前路径的权取最大值 dfs(shu[f][i], f, max(w, cost[f][shu[f][i]]), root); } } int krusal() { int num = 0; sort(edug,edug + m,cmp); for (int i = 0; i < m; i++) { if (combine(edug[i].from, edug[i].to, edug[i].w, i)) num++; if (num == n - 1) break; } for (int i = 0; i < vis.size(); i++) { memset(hash1, false, sizeof(hash1)); dfs(vis[i], -1, 0, vis[i]); } int sum = 0x3f3f3f3f; for (int i = 0; i < m; i++) { if (used[i]) continue; int u = edug[i].from; int v = edug[i].to; int w = edug[i].w; sum = min(ans + w - maxcost[u][v],sum);//逐一减去这个边加上不是最小生成树的边再取最小值便是次小生成树了 } if (sum == ans) cout << "Not Unique!" << endl; else cout << ans << endl; return 0; } int main() { int t; cin >> t; while (t--) { cin >> n >> m; init(); for (int i = 0; i < m; i++) { cin >> edug[i].from >> edug[i].to >> edug[i].w; } krusal(); } }
相关文章推荐
- Win2003利用dfs(分布式文件系统)在负载均衡下的文件同步配置方案
- win2003分布式文件系统(dfs)配置方法[图文详解]
- win2003分布式文件系统及其部署 图文教程
- 简单的四则运算
- 数的奇偶性
- Hadoop2.6+jdk8的安装部署(1)——使用jar包安装部署【详细】
- Hadoop FS Shell
- DFS使用方法总结
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- FastDFS注意事项
- 无忧技术带您预览DFS(分布式文件系统)管理控制台
- 矩阵的乘法操作
- C 语言实现迷宫 DFS算法
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置