UVALive 6837 (最小生成树)
2015-12-07 13:32
477 查看
题意是给定一个联通图,求这个图的最小生成树的不可替代边有哪些,并计算这些边的总权值.
先求出任意一棵MST,然后标记树边和非树边,然后枚举非树边,对于非树边的两个点u,v,在MST中如果u->v的路径上有边的权值等于这条非树边的权值那么这条树边就是可替代边,给它打上标记.u->v的路径可以通过u->LCA(u,v), v->LCA (u,v)暴力枚举.
复杂度(m*n).
先求出任意一棵MST,然后标记树边和非树边,然后枚举非树边,对于非树边的两个点u,v,在MST中如果u->v的路径上有边的权值等于这条非树边的权值那么这条树边就是可替代边,给它打上标记.u->v的路径可以通过u->LCA(u,v), v->LCA (u,v)暴力枚举.
复杂度(m*n).
<span style="font-size:12px;">#include <bits/stdc++.h> using namespace std; #define maxn 1111 #define maxm 511111 #define find Find struct node1 { int u, v, w; bool vis; bool operator < (node1 a) const { return w < a.w; } }e[maxm]; struct node2 { int u, v, w, next; bool vis; }edge[maxm]; int head[maxn], fa[maxn], n, m; int cnt; int MST; int find (int x) { return fa[x] == x ? fa[x] : fa[x] = find (fa[x]); } void add_edge (int u, int v, int w) { edge[cnt].vis = 0; edge[cnt].u = u, edge[cnt].v = v, edge[cnt].w = w, edge[cnt].next = head[u], head[u] = cnt++; } void kruscal () { for (int i = 1; i <= n; i++) fa[i] = i; int num = 0; MST = 0; for (int i = 1; i <= m; i++) { int u = e[i].u, v = e[i].v, w = e[i].w; int p1 = find (u), p2 = find (v); if (p1 != p2) { fa[p1] = p2; add_edge (u, v, w); add_edge (v, u, w); num++; MST += e[i].w; e[i].vis = 1; } if (num == n-1) break; } } int d[maxn]; void dfs (int u, int fa, int deep) { d[u] = deep; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if (v == fa) continue; dfs (v, u, deep+1); } } void work (int u, int v, int w) { if (u == v) { return ; } if (d[u] < d[v]) swap (u, v); for (int i = head[u]; i != -1; i = edge[i].next) { int to = edge[i].v; if (d[to] > d[u]) continue ; if (edge[i].w == w) { edge[i].vis = edge[i^1].vis = 1; } work (to, v, w); } } void solve () { kruscal (); dfs (1, 0, 1); for (int i = 1; i <= m; i++) { if (!e[i].vis) { work (e[i].u, e[i].v, e[i].w); } } int ans = 0; for (int i = 0; i < cnt; i += 2) { if (edge[i].vis) MST -= edge[i].w; else ans++; } printf ("%d %d\n", ans, MST); } int main () { //freopen ("in", "r", stdin); while (scanf ("%d%d", &n, &m) == 2) { for (int i = 1; i <= m; i++) { int u, v, w; scanf ("%d%d%d", &u, &v, &w); e[i].u = u, e[i].v = v, e[i].w = w; e[i].vis = 0; } memset (head, -1, sizeof head); cnt = 0; sort (e+1, e+1+m); solve (); } return 0; } </span>
相关文章推荐
- mybatis入门例子
- 微软算法100题69 求旋转数组中的最小元素
- 解决Toast不显示问题 Toast invisible to user . go ahead
- 循环的理解和比较
- 博客csdn
- ECSHOP后台SQL查询提示错误 this sq May contain
- 列表中的导航菜单的制作
- MySQL之Xtrabackup备份恢复数据库-简介
- Android监听键盘状态变化
- C#类型转换总结(三)各类型转化实例
- HDU 5592 ZYB's Premutation
- jsp Request获取url信息的各种方法比较
- Java数据库连接(JDBC)【整理】
- SHELL编程
- JSP内置对象
- quick-cocos2d-x游戏开发【6】——制作您自己的自定义效果button菜单
- ,工程项目创建流程,目录结构的一半格式,工程中pod进来的用<>,bundle命名的作用,用处怎么用兼容读个版本,pch文件创建
- Android功能组件源代码分析之二《AmazingListView》
- ios8 点击设置->隐私->定位服务手机闪退
- 关于GOP:M=3,N=12