http://www.lydsy.com/JudgeOnline/problem.php?id=1937 (题目链接)

题意

  一个无向图,给出一个生成树,可以修改每条边的权值,问最小修改多少权值使得给出的生成树是最小生成树。

Solution

  好神!!!!!

  首先,由贪心可知,生成树上的边我们肯定是减小它的权值,非树边我们肯定是增大它的权值。假设树边$i$的权值$w_i$,修改后的权值$w_i-d_i$;非树边$j$的权值$w_j$,修改后的权值$w_j+d_j$。如果$j$有可能代替$i$,那么它们必须满足式子$w_i-d_i<=w_j+d_j$,移下项$w_i-w_j<=d_i+d_j$,是不是很像KM里面的顶标,所以我们把边当做点,边权为两个有制约关系的边的权值差,跑KM求最大权完美匹配就可以了。

  纠结了好久,蛋疼死了。我们的确是要求最小的$\sum d_i$,但是$w_i-w_j<=d_i+d_j$的意义是要求对所有的$i,j$都得满足。我们需要在满足条件的情况下不断缩小$\sum d_i$,所以完美匹配以后我们可以使$\sum d_i$最小。

细节

  边权非负。可能不会完美匹配,需要加点加边。

代码

  1. // bzoj1937
  2. #include<algorithm>
  3. #include<iostream>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<cstdio>
  7. #include<cmath>
  8. #include<queue>
  9. #define LL long long
  10. #define inf (1ll<<30)
  11. #define MOD 1000000007
  12. #define Pi acos(-1.0)
  13. #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
  14. using namespace std;
  15.  
  16. const int maxn=1010;
  17. int head[maxn],deep[maxn],vis[maxn],fa[maxn],id[maxn][maxn],n,m,cnt;
  18. int slack[maxn],vx[maxn],vy[maxn],lx[maxn],ly[maxn],p[maxn],mp[maxn][maxn];
  19. struct data {int u,v,w;}a[maxn];
  20. struct edge {int to,next;}e[maxn<<1];
  21.  
  22. void link(int u,int v) {
  23. e[++cnt]=(edge){v,head[u]};head[u]=cnt;
  24. e[++cnt]=(edge){u,head[v]};head[v]=cnt;
  25. }
  26. void dfs(int x) {
  27. for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x]) {
  28. deep[e[i].to]=deep[x]+1;
  29. fa[e[i].to]=x;
  30. dfs(e[i].to);
  31. }
  32. }
  33. bool match(int x) {
  34. vx[x]=cnt;
  35. for (int y=1;y<=m;y++) if (vy[y]!=cnt) {
  36. int t=lx[x]+ly[y]-mp[x][y];
  37. if (!t) {
  38. vy[y]=cnt;
  39. if (!p[y] || match(p[y])) {p[y]=x;return 1;}
  40. }
  41. else slack[y]=min(slack[y],t);
  42. }
  43. return 0;
  44. }
  45. int KM() {
  46. for (int i=1;i<=m;i++) {
  47. lx[i]=-inf;
  48. for (int j=1;j<=m;j++) lx[i]=max(lx[i],mp[i][j]);
  49. }
  50. cnt=0;
  51. for (int x=1;x<=m;x++) {
  52. for (int i=1;i<=m;i++) slack[i]=inf;
  53. while (1) {
  54. int d=inf;cnt++;
  55. if (match(x)) break;
  56. for (int i=1;i<=m;i++) if (vy[i]!=cnt) d=min(d,slack[i]);
  57. for (int i=1;i<=m;i++) {
  58. if (vx[i]==cnt) lx[i]-=d;
  59. if (vy[i]==cnt) ly[i]+=d;
  60. }
  61. }
  62. }
  63. int ans=0;
  64. for (int i=1;i<=m;i++) ans+=mp[p[i]][i];
  65. return ans;
  66. }
  67. int main() {
  68. scanf("%d%d",&n,&m);
  69. for (int i=1;i<=m;i++) {
  70. scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
  71. id[a[i].u][a[i].v]=id[a[i].v][a[i].u]=i;
  72. }
  73. for (int u,v,i=1;i<n;i++) {
  74. scanf("%d%d",&u,&v);
  75. link(u,v);vis[id[u][v]]=1;
  76. }
  77. dfs(1);memset(head,0,sizeof(head));cnt=0;
  78. for (int i=1;i<=m;i++) if (!vis[i]) {
  79. int x=a[i].u,y=a[i].v,w=a[i].w;
  80. if (deep[x]<deep[y]) swap(x,y);
  81. int t=deep[x]-deep[y];
  82. while (t--) mp[id[x][fa[x]]][i]=max(0,a[id[x][fa[x]]].w-w),x=fa[x];
  83. while (x!=y) {
  84. mp[id[x][fa[x]]][i]=max(0,a[id[x][fa[x]]].w-w);
  85. mp[id[y][fa[y]]][i]=max(0,a[id[y][fa[y]]].w-w);
  86. x=fa[x],y=fa[y];
  87. }
  88. }
  89. printf("%d",KM());
  90. return 0;
  91. }

【bzoj1937】 Shoi2004—Mst 最小生成树的更多相关文章

  1. [BZOJ1937][SHOI2004]Mst最小生成树(KM算法,最大费用流)

    1937: [Shoi2004]Mst 最小生成树 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 802  Solved: 344[Submit][Sta ...

  2. 【KM】BZOJ1937 [Shoi2004]Mst 最小生成树

    这道题拖了好久因为懒,结果1A了,惊讶∑( 口 || [题目大意] 给定一张n个顶点m条边的有权无向图.现要修改各边边权,使得给出n-1条边是这张图的最小生成树,代价为变化量的绝对值.求最小代价之和. ...

  3. BZOJ1937 [Shoi2004]Mst 最小生成树

    首先由贪心的想法知道,树边只减不加,非树边只加不减,令$w_i$表示i号边原来的边权,$d_i$表示i号边的改变量 对于一条非树边$j$连接着两个点$x$.$y$,则对于$xy$这条路径上的所有树边$ ...

  4. 【BZOJ1937】[Shoi2004]Mst 最小生成树 KM算法(线性规划)

    [BZOJ1937][Shoi2004]Mst 最小生成树 Description Input 第一行为N.M,其中 表示顶点的数目, 表示边的数目.顶点的编号为1.2.3.…….N-1.N.接下来的 ...

  5. BZOJ 1937: [Shoi2004]Mst 最小生成树 [二分图最大权匹配]

    传送门 题意: 给一张无向图和一棵生成树,改变一些边的权值使生成树为最小生成树,代价为改变权值和的绝对值,求最小代价 线性规划的形式: $Min\quad \sum\limits_{i=1}^{m} ...

  6. [BZOJ 1937][Shoi2004]Mst 最小生成树

    传送门 $ \color{red} {solution:} $ 对于每条树边\(i\),其边权只可能变小,对于非树边\(j\),其边权只可能变大,所以对于任意非树边覆盖的树边有 \(wi - di & ...

  7. MST最小生成树

    首先,贴上一个很好的讲解贴: http://www.wutianqi.com/?p=3012 HDOJ 1233 还是畅通工程 http://acm.hdu.edu.cn/showproblem.ph ...

  8. [poj1679]The Unique MST(最小生成树)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28207   Accepted: 10073 ...

  9. UVA 1151 Buy or Build (MST最小生成树,kruscal,变形)

    题意: 要使n个点之间能够互通,要使两点直接互通需要耗费它们之间的欧几里得距离的平方大小的花费,这说明每两个点都可以使其互通.接着有q个套餐可以选,一旦选了这些套餐,他们所包含的点自动就连起来了,所需 ...

随机推荐

  1. 2.2 Oracle之DML的SQL语句之多表查询以及组函数

    一.SQL的多表查询: 1.左连接和右连接(不重要一方加(+)) SELECT e.empno,e.ename,d.deptno,d.dname,d.loc FROM emp e,dept d WHE ...

  2. SQL Operations Studio的安装和使用

    之前管理和访问SQL SERVER使用的自然是SSMS,功能确实很强大的一个数据库图形化管理软件,但是SSMS有个问题就是体积超级大,启动速度也就比较慢.今天我正好要学习一些T-SQL的内容,在微软的 ...

  3. kubernetes高可用设计-master节点和kubectl

    部署master 节点 上一遍是CA证书和etcd的部署,这一篇继续搭建k8s,废话不多说.开始部署. kubernetes master 节点包含的组件有: kube-apiserver kube- ...

  4. 点斜杠 & 如何查看linux程序安装位置 dpkg -L yyy

    方法1: sudo find / -name ssh 方法2: Ubuntu下 看应用程序安装路径的方法 ubuntu下dpkg -L xxx看应用程序安装路径 1.点斜杠 “./”就代表在当前目录下 ...

  5. SQL-Server collation, what is it and how to change db/column collation

    The thing about collations is that although database have it's own collation, every table, and every ...

  6. Appengine直接下载文件并保存到google drive

    一直对下载文件比较感兴趣.前些日子无意搜到google 推出一项服务,可以直接将文件下载到google drive中,原型猛戳这里,但有限额限制.一时脑洞大开,可不可以在appengine 上架设服务 ...

  7. chown命令详情

    基础命令学习目录首页 原文链接:https://www.jb51.net/article/98255.htm chown将指定文件的拥有者改为指定的用户或组,用户可以是用户名或者用户ID:组可以是组名 ...

  8. PHP中 post方法 与 get方法 的区别

    1.Get 方法通过 URL 请求来传递用户的数据,将表单内各字段名称与其内容,以成对的字符串连接,置于 action 属性所指程序的 url 后,如[url]http://www.domain.co ...

  9. Mongodb For Mac OSX && 登录验证

    题外话:尽管有不少人贴出了 <我不用mongodb的十大理由> 等系列文章,但是 NoSQL 的发展不会因此而止步, mongodb 是 NoSQL 的典型代表,楼主还是抱乐观态度的,有人 ...

  10. win10系统下载-靠谱推荐

    win10系统下载的靠谱推荐: 1.http://www.xitongtiandi.net/wenzhang/win10/12926.html 2.https://msdn.itellyou.cn/ ...