Ural 1416 Confidential(最小生成树+次小生成树)
来源:互联网 发布:nginx ip映射域名 编辑:程序博客网 时间:2024/06/11 08:21
题意:给n个点m条边,求它的最小生成树和次小生成树的权值分别是多少。
思路:先求最小生成树,并查集即可,求出来之后求次小生成树,次小生成树一定是在最小生成树的基础上添加一条边在之后形成的环中删除除了加入的边中的最大的一条边,然后枚举所有未添加的边。求两点之间路径上的最大权的边,可以预处理出LCA,然后查询log n,就可以了。
#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<set>#include<algorithm>const int maxn = 1e3 + 10;const int INF = 1e9;using namespace std;struct P { int u, v, cost; P() {} P(int u, int v, int c) : u(u), v(v), cost(c) {} bool operator < (P p) const { return cost < p.cost; } void input() { scanf("%d %d %d", &u, &v, &cost); }} tr[maxn * maxn];int n, m, pre[maxn], c[maxn];int use[maxn * maxn];int vis[maxn], p[maxn], deep[maxn];int anc[maxn][30], cost[maxn][30];vector<P> G[maxn];void init() { for(int i = 0; i < maxn; i++) { G[i].clear(); pre[i] = i; } memset(use, 0, sizeof use); memset(vis, 0, sizeof vis);}int findset(int x) { return pre[x] = (x == pre[x] ? x : findset(pre[x])); }void dfs(int x, int k) { vis[x] = 1; deep[x] = k; for(int i = 0; i < G[x].size(); i++) { int v = G[x][i].v; if(vis[v]) continue; p[v] = x; dfs(v, k + 1); c[v] = G[x][i].cost; }}void preprocess() { for(int i = 1; i <= n; i++) { anc[i][0] = p[i]; cost[i][0] = c[i]; for(int j = 1; (1 << j) < n; j++) anc[i][j] = -1; } for(int j = 1; (1 << j) < n; j++) { for(int i = 1; i <= n; i++) { if(anc[i][j - 1] == -1) continue; int a = anc[i][j - 1]; anc[i][j] = anc[a][j - 1]; cost[i][j] = max(cost[i][j - 1], cost[a][j - 1]); } }}int query(int p, int q) { int lg; if(deep[p] < deep[q]) swap(p, q); for(lg = 1; (1 << lg) <= deep[p]; lg++); lg--; int ans = 0; for(int i = lg; i >= 0; i--) { if(deep[p] - (1 << i) >= deep[q]) { ans = max(ans, cost[p][i]); p = anc[p][i]; } } if(p == q) return ans; for(int i = lg; i >= 0; i--) { if(anc[p][i] != -1 && anc[p][i] != anc[q][i]) { ans = max(ans, cost[p][i]); p = anc[p][i]; ans = max(ans, cost[q][i]); q = anc[q][i]; } } ans = max(ans, max(c[p], c[q])); return ans;}int main() { while(scanf("%d %d", &n, &m) != EOF) { init(); for(int i = 0; i < m; i++) tr[i].input(); sort(tr, tr + m); int ans1 = 0, ans2 = INF, edge = 0; for(int i = 0; i < m; i++) { int u = tr[i].u, v = tr[i].v; int nx = findset(u), ny = findset(v); if(nx == ny) continue; pre[nx] = ny; ans1 += tr[i].cost; edge++; use[i] = 1; G[u].push_back(P(u, v, tr[i].cost)); G[v].push_back(P(v, u, tr[i].cost)); } if(edge < n - 1) ans1 = -1; if(ans1 != -1) { p[1] = -1; c[1] = 0; dfs(1, 1); preprocess(); for(int i = 0; i < m; i++) { if(use[i]) continue; int u = tr[i].u, v = tr[i].v; int add = query(u, v); ans2 = min(ans2, ans1 + tr[i].cost - add); } } if(ans2 == INF) ans2 = -1; printf("Cost: %d\nCost: %d\n", ans1, ans2); } return 0;}
0 0
- Ural 1416 Confidential,次小生成树
- URAL - 1416 Confidential(次小生成树)
- URAl 1416Confidential【次小生成树】
- Ural 1416 Confidential(最小生成树+次小生成树)
- URAL 1416 Confidential --最小生成树与次小生成树
- URAL 1416 Confidential <最小生成数和次小生成数>
- poj1679 The Unique MST(次小生成树) Ural 1416 Confidential
- Confidential----Ural_1416----次小生成树
- 次小。最小生成树
- 最小生成树-->次小生成树
- 最小生成树&&次小生成树
- 最小生成树,次小生成树
- URAL-1416 (典型的次小生成树)
- 判断唯一最小生成树(次小生成树)
- poj 1679 最小 次小生成树
- 最小生成树和次小生成树
- hdu 4801 最小比率生成树 次小生成树
- 最小生成树和次小生成树
- Android冷启动实现APP秒开
- 正则表达式替换tab键、换行键
- JVM内存配置详解
- AVL
- android 5.1源码 去除搜索栏
- Ural 1416 Confidential(最小生成树+次小生成树)
- MD5加密
- replica character liquid crystal display control
- 专访DeepID发明者孙祎:关于深度学习与人脸算法的深层思考
- struts2 文件上传
- PAT 1117 Eddington Number
- cron表达式用法说明
- HTTp缓存机制及原理
- 31届宁波市中小学生程序设计竞赛复赛(初中组)