题意:给定N个点,M条边,M >= N-1。已知M条边都有一个权值,已知前N-1边能构成一颗N个节点生成树,现问通过修改这些边的权值使得最小生成树为前N条边的最小改动总和为多少?

分析:由于计算的最小改动且为最小生成树则显然前N-1条边肯定权值都减少,后面的边权值都增加。由于选择的边为前N-1得到最小生成树,因此首先将N-1条边构图,然后对后面的每一条边,那么这条边所构成的环中,有任意一条边的a与该边b,设原始权重为w[a],w[b],改变量为d[a],w[b],则有w[a] - d[a] <= w[b] + d[b],移项后有w[a] - w[b] <= d[a] + d[b],而我们要求的 d[] 数组的和值的最小值。可以将所有的 d[x] 看作是x节点(边)的权值,则此题相当于给每个节点(边)分配一个权值,使得满足所有环中的不等式,也就是求一个最小权值匹配,其对偶问题就是构图之后的最大权值匹配问题,可行标的值就是需要分配的权值。本题有一个隐含的条件就是d[i] + d[j] >= 0表现在图中就是每个点对之间连了一条权值为0的边,这样才能够保证求出来的值都是正值。

简要分析其原理:首先最大权值匹配算法的初始化就是选择的最大的边设定可行标,且算法在始终不会改变已经匹配边的左右可行标之和的情况下,不停的扩充权值更小的边进入子图,因此其最后得到的最大匹配一定能够保证所有的边左右端点可行标之和大于等于该边权值。其次,如果一个匹配不是最大匹配,那么既然存在最大匹配那么说明肯定有某条本应该在最大匹配中的边没有加入到子图中且该边的左右端点可行标之和小于该边的权值,否则与假设矛盾。

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;const int N = 65;
const int M = 405;
const int inf = 0x3f3f3f3f;
int cn[N][N]; // 原图中的边
int w[M][M]; // 二分图中边的关系
int lx[M], ly[M];
char vx[M], vy[M];
int match[M];
int slack[M];
int n, m, nm;
struct Edge {int a, b, c;
}e[M];bool dfs(int p, int u, int id) {for (int i = 1; i <= n; ++i) {if (i == p) continue;if (cn[u][i] == id) return true;if (cn[u][i] != 0 && dfs(u, i, id)) {w[cn[u][i]][id-(n-1)] = max(e[cn[u][i]].c - e[id].c, 0);return true;}}return false;
}bool path(int u) {vx[u] = 1;for (int i = 1; i <= nm; ++i) {if (vy[i]) continue;if (lx[u] + ly[i] == w[u][i]) {vy[i] = 1;if (match[i] == -1 || path(match[i])) {match[i] = u;return true;}} else {slack[i] = min(slack[i], lx[u]+ly[i]-w[u][i]);}}return false;
}void KM() {memset(match, 0xff, sizeof (match));memset(ly, 0, sizeof (ly));memset(lx, 0x80, sizeof (lx));for (int i = 1; i <= nm; ++i) {for (int j = 1; j <= nm; ++j) {lx[i] = max(lx[i], w[i][j]);}}for (int i = 1; i <= nm; ++i) {int cnt = 0;while (1) {memset(slack, 0x3f, sizeof (slack));memset(vx, 0, sizeof (vx));memset(vy, 0, sizeof (vy));if (path(i)) break;int d = inf;for (int j = 1; j <= nm; ++j) if (!vy[j]) d = min(d, slack[j]);for (int j = 1; j <= nm; ++j) if (vx[j]) lx[j] -= d;for (int j = 1; j <= nm; ++j) {if (vy[j]) ly[j] += d;else slack[j] -= d;}}}
}int main() {int T, a, b, c;scanf("%d", &T);while (T--) {scanf("%d %d", &n, &m);memset(cn, 0, sizeof (cn));memset(w, 0, sizeof (w));for (int i = 1; i <= m; ++i) {scanf("%d %d %d", &a, &b, &c);if (i < n) cn[a][b] = cn[b][a] = i;e[i].a = a, e[i].b = b, e[i].c = c;}for (int i = n; i <= m; ++i) {cn[e[i].b][e[i].a] = i;dfs(0, e[i].a, i);cn[e[i].b][e[i].a] = 0;}nm = max(n-1, m-(n-1));KM();for (int i = 1; i < n; ++i) printf("%d\n", e[i].c-lx[i]);for (int i = 1; i <= m-(n-1); ++i) printf("%d\n", e[i+n-1].c+ly[i]);}return 0;
}

转载于:https://www.cnblogs.com/Lyush/p/3307786.html

ZOJ-2342 Roads 二分图最小权值覆盖相关推荐

  1. HDU 1853 HDU 3488【有向环最小权值覆盖问题 】带权二分图匹配 KM算法

    HDU 1853 & HDU 3488[有向环最小权值覆盖问题 ]最小费用最大流 In the kingdom of Henryy, there are N (2 <= N <= ...

  2. HDU 1853 HDU 3488【有向环最小权值覆盖问题 】最小费用最大流

    HDU 1853 & HDU 3488[有向环最小权值覆盖问题 ]带权二分图匹配 KM算法 In the kingdom of Henryy, there are N (2 <= N & ...

  3. HDU - 3488 Tour(二分图最小权匹配+KM)

    题目链接:点击查看 题目大意:给出n个城市,再给出m条有向的道路,问若想以一个或多个环的形式遍历所有的城市一次,所需要的最小权值是多少 题目分析:刚拿到这个题目是有点懵的,因为不知道题目让求什么,其实 ...

  4. 利用Kuhn-Munkras算法求最小权值匹配

    本文参考博客: http://blog.csdn.net/zhangpinghao/article/details/12242823(代码参考该博客) http://philoscience.itey ...

  5. P2172 [国家集训队]部落战争 二分图最小不相交路径覆盖

    二分图最小不相交路径覆盖 #include<bits/stdc++.h> using namespace std; const int MAXN = 5550; const int MAX ...

  6. poj3686(最小权值完美匹配)

    开始理解的有点简单了,也是看了其他的博客之后发现问题的: 题意:因为每一个物件都是受前一个物件的时间限制,所以假设某台机器加工了k个订单,那么用时为t1 + (t1 + t2) + (t1 + t2 ...

  7. HDU6346(最小权值完美匹配)

    题意:满足 xi+yj≤ai,j(1≤i,j≤n) 的约束下最大化∑ni=1xi+∑ni=1yi, 思路:采用最大权值完美匹配算法:但是现在这里是求最小权值完美匹配问题,所以只需要将权值取反最后在取反 ...

  8. POJ-2195 Going Home 最小权值匹配

    题意:给定一个网格图,图上有一些人要到一些房子当中去,人和房子的数量一样多,人和房子的曼哈顿距离作为行走的开销,问所有人走到房子中的最小开销. 解法:将人和房子之间两两之间建立带权边,权值为曼哈顿距离 ...

  9. UVA 1349 Optimal Bus Route Design (二分图最小权完美匹配)

    恰好属于一个圈,那等价与每个点有唯一的前驱和后继,这让人想到了二分图, 把一个点拆开,点的前驱作为S集和点的后继作为T集,然后连边,跑二分图最小权完美匹配. 写的费用流..最大权完美匹配KM算法没看懂 ...

最新文章

  1. Centos 7 解压文件
  2. Hadoop教程(二):安装
  3. 在GLSurfaceView上添加Layout控件(android)
  4. 【CV】使用 OpenCV 进行图像中的性别预测和年龄检测
  5. 斩获2019 Thales AIChallenge4Health第一,腾讯优图医疗AI再获突破
  6. Python开发者必知的 11 个 Python GUI 库,你用过几个?
  7. 递归——数的计算(洛谷 P1028)
  8. [转]关于Python里的类型注解
  9. webbench 压力测试软件
  10. 46多项式01——一元多项式和运算
  11. c#关于try catch finally的使用,判断日期格式是否正确
  12. 第一个动态网页——留言板
  13. sfc/Windows 资源保护找到了损坏文件但无法修复
  14. VNC_Linux环境服务安装、配置与使用
  15. 后端:发送短信(腾讯云)-nodejs
  16. 暑假来了,画一个日月地球的轨道模型给孩子们,秒懂四季更迭、日蚀月蚀
  17. 高性能Excel操作工具
  18. 全国计算机一级上表格怎么做,全国计算机一级考试word表格制作(2003版)
  19. python枚举窗口句柄_如何使用 WIN32 API 枚举窗口?
  20. 怎样阅读论文(台湾彭明辉)ZT

热门文章

  1. python随机列表文本_在python中从单词列表返回随机单词
  2. Problem 1: Multiples of 3 and 5
  3. RSA加密算法的简单案例
  4. 【BZOJ-1952】城市规划 [坑题] 仙人掌DP + 最大点权独立集(改)
  5. VS2010可反复安装MSDN的方法
  6. 在awk中执行外部命令
  7. 发现读纸质媒介比电子媒介的乐趣大多了
  8. 从无到有整合SpringMVC-MyBatis项目(2):搭建SpringMVC项目
  9. JavaScript——面向对象之继承(原型对象)与多态(重载、重写)
  10. Day12-流Stream