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

Input
第一行为N、M,其中 表示顶点的数目, 表示边的数目。顶点的编号为1、2、3、……、N-1、N。接下来的M行,每行三个整数Ui,Vi,Wi,表示顶点Ui与Vi之间有一条边,其权值为Wi。所有的边在输入中会且仅会出现一次。再接着N-1行,每行两个整数Xi、Yi,表示顶点Xi与Yi之间的边是T的一条边。
Output
输出最小权值
Sample Input
1 2 2
1 3 2
2 3 3
3 4 3
1 5 1
2 6 3
4 5 4
4 6 7
5 6 6
1 3
2 3
3 4
4 5
4 6
Sample Output
【样例说明】
边(4,6)的权由7修改为3,代价为4
边(1,2)的权由2修改为3,代价为1
边(1,5)的权由1修改为4,代价为3
所以总代价为4+1+3=8
修改方案不唯一。
HINT
1<=n<=50,1<=m<=800,1<=wi<=1000
n-->点数..m-->边数..wi--->边权
题解:神题~
显然,树边的权值一定减小,非树边的权值一定增大,所以如果非树边j覆盖了树边i,则有wj+dj>=wi-di,即di+dj>=wi-wj。所以这。。。tm是KM算法中的顶标?
复习KM的原理,KM算法就是始终满足:对于每条边a-b,l(a)+l(b)>=v(a,b),并且所有l(a)+l(b)=v(a,b)的边构成的子图叫相等子图。并在满足上述条件下不断调整定标,使得相等子图不断扩大。
而对于本题,让wi-wj就是边权,然后求出最优匹配既是答案。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,m,Cnt,nm,ans;
int map[60][60],pa[810],pb[810],pc[810],To[110],Next[110],Val[110],Head[60],len[60];
int fa[60],dep[60],bel[60],la[60],lb[810],va[60],vb[810],from[810],v[60][810];
inline void Add(int a,int b,int c)
{
To[Cnt]=b,Val[Cnt]=c,Next[Cnt]=Head[a],Head[a]=Cnt++;
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
void Dfs(int x)
{
for(int i=Head[x];i!=-1;i=Next[i]) if(To[i]!=fa[x]) fa[To[i]]=x,dep[To[i]]=dep[x]+1,bel[To[i]]=Val[i],Dfs(To[i]);
}
void build(int a,int b,int c)
{
if(dep[a]<dep[b]) swap(a,b);
while(dep[a]>dep[b]) v[bel[a]][nm]=max(0,len[bel[a]]-c),a=fa[a];
while(a!=b) v[bel[a]][nm]=max(0,len[bel[a]]-c),v[bel[b]][nm]=max(0,len[bel[b]]-c),a=fa[a],b=fa[b];
}
int dfs(int x)
{
va[x]=1;
for(int y=1;y<=nm;y++) if(!vb[y]&&la[x]+lb[y]==v[x][y])
{
vb[y]=1;
if(!from[y]||dfs(from[y]))
{
from[y]=x;
return 1;
}
}
return 0;
}
int main()
{
n=rd(),m=rd();
int i,j,k,a,b;
memset(Head,-1,sizeof(Head));
for(i=1;i<=m;i++) pa[i]=rd(),pb[i]=rd(),pc[i]=rd(),map[pa[i]][pb[i]]=map[pb[i]][pa[i]]=i;
for(i=1;i<n;i++)
{
a=rd(),b=rd(),Add(a,b,i),Add(b,a,i),len[i]=pc[map[a][b]],map[a][b]=map[b][a]=0;
}
dep[1]=1,Dfs(1);
for(i=1;i<=m;i++) if(map[pa[i]][pb[i]])
{
nm++;
build(pa[i],pb[i],pc[i]);
}
for(i=1;i<=n;i++) for(j=1;j<=nm;j++) la[i]=max(la[i],v[i][j]);
for(i=1;i<=n;i++)
{
while(1)
{
memset(va,0,sizeof(va)),memset(vb,0,sizeof(vb));
if(dfs(i)) break;
int tmp=1<<30;
for(j=1;j<=n;j++) if(va[j]) for(k=1;k<=nm;k++) if(!vb[k]) tmp=min(tmp,la[j]+lb[k]-v[j][k]);
if(tmp==1<<30) break;
for(j=1;j<=n;j++) if(va[j]) la[j]-=tmp;
for(j=1;j<=nm;j++) if(vb[j]) lb[j]+=tmp;
}
}
for(i=1;i<=n;i++) ans+=la[i];
for(i=1;i<=nm;i++) ans+=lb[i];
printf("%d",ans);
return 0;
}
【BZOJ1937】[Shoi2004]Mst 最小生成树 KM算法(线性规划)的更多相关文章
- [BZOJ1937][SHOI2004]Mst最小生成树(KM算法,最大费用流)
1937: [Shoi2004]Mst 最小生成树 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 802 Solved: 344[Submit][Sta ...
- BZOJ1937 [Shoi2004]Mst 最小生成树
首先由贪心的想法知道,树边只减不加,非树边只加不减,令$w_i$表示i号边原来的边权,$d_i$表示i号边的改变量 对于一条非树边$j$连接着两个点$x$.$y$,则对于$xy$这条路径上的所有树边$ ...
- 【KM】BZOJ1937 [Shoi2004]Mst 最小生成树
这道题拖了好久因为懒,结果1A了,惊讶∑( 口 || [题目大意] 给定一张n个顶点m条边的有权无向图.现要修改各边边权,使得给出n-1条边是这张图的最小生成树,代价为变化量的绝对值.求最小代价之和. ...
- [BZOJ 1937][Shoi2004]Mst 最小生成树
传送门 $ \color{red} {solution:} $ 对于每条树边\(i\),其边权只可能变小,对于非树边\(j\),其边权只可能变大,所以对于任意非树边覆盖的树边有 \(wi - di & ...
- 【bzoj1937】 Shoi2004—Mst 最小生成树
http://www.lydsy.com/JudgeOnline/problem.php?id=1937 (题目链接) 题意 一个无向图,给出一个生成树,可以修改每条边的权值,问最小修改多少权值使得给 ...
- BZOJ 1937: [Shoi2004]Mst 最小生成树 [二分图最大权匹配]
传送门 题意: 给一张无向图和一棵生成树,改变一些边的权值使生成树为最小生成树,代价为改变权值和的绝对值,求最小代价 线性规划的形式: $Min\quad \sum\limits_{i=1}^{m} ...
- MST(最小生成树)——Prim算法——HDU 1879-继续畅通工程
Prim算法很好理解,特别是学完了迪杰斯特拉算法之后,更加能理解Prim的算法思想 和迪杰斯特拉算法差不多,由于最后要形成连通图,故任意指定一个点,作为初始点,遍历所有点,以当前最小权值的点(和迪杰斯 ...
- 最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind
最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小 ...
- 图论算法(五)最小生成树Prim算法
最小生成树\(Prim\)算法 我们通常求最小生成树有两种常见的算法--\(Prim\)和\(Kruskal\)算法,今天先总结最小生成树概念和比较简单的\(Prim\)算法 Part 1:最小生成树 ...
随机推荐
- asp.net+mvc+easyui+sqlite 简单用户系统学习之旅(四)—— session传递登录人信息显示+用户注销
前面的学习,已经做好了简单的登录和主页,涉及了三层软件架构,mvc,easyui的layout.tree.tab.window,sqlite,动软代码自动生成. 下面完善一下登录跳转主页后,在sout ...
- FileNotFoundException: http:\localhos46087125.jpg (文件名、目录名或卷标语法不正确
java.io.FileNotFoundException: http:\localhost:8080\ipms\upload\1332146087125.jpg (文件名.目录名或卷标语法不正确.) ...
- Google I/O 2014 大会总结 Android开发新方向
昨天晚上,Google I/O 2014大会召开,会上主要展示了下面几个部分的创新内容: Android L 操作系统 首先是界面,谷歌又一次设计了一套 UI 规范.并称之为"Materia ...
- c语言编写51单片机中断程序,执行过程是怎样的?
Q:c语言编写51单片机中断程序,执行过程是怎样的? 例如程序:#include<reg52.h> void main(void) { EA=1; //开放总中断 E ...
- Linux操作系统下/etc/hosts文件配置方法
1.关于/etc/host,主机名和IP配置文件 Hosts - The static table lookup for host name(主机名查询静态表) hosts文件是Linux系统中一个负 ...
- PILE读书笔记_进程环境
进程是操作系统运行程序的一个实例, 也是操作系统分配资源的单位. 在Linux环境中, 每个进程都有独立的进程空间, 以便对不同的进程进行隔离, 使之不会互相影响. atexit函数 #include ...
- libevent源码学习_event_test
对应的sample文件中提供了event_test.c,里面就是关于事件的简单示例,具体如下: /* * Compile with: * cc -I/usr/local/include -o even ...
- std::vector
Vector Vectors are sequence containers representing arrays that can change in size. Just like arrays ...
- 华为终端开放实验室Android P Beta 4测试能力上线
7月26日,Android P Beta 4发布(即Android P DP5),此版本为开发者最后一个预览版本,也预示着Android P正式版即将与大家见面. 为保证开发者在正式版本来临前做好充分 ...
- 服务器操作系统应该选择Debian/Ubuntu还是CentOS?
任何 Linux 发行版本,在理论上都是一样的.只不过操作有的方便,有的麻烦!yum 是比 apt 弱(这就是企业维护和社区维护的区别,企业自己维护不需要这么多功能)但是任何能在 A 发行版本上实现的 ...