【bzoj1937】 Shoi2004—Mst 最小生成树
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$最小。
细节
边权非负。可能不会完美匹配,需要加点加边。
代码
// bzoj1937
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf (1ll<<30)
#define MOD 1000000007
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=1010;
int head[maxn],deep[maxn],vis[maxn],fa[maxn],id[maxn][maxn],n,m,cnt;
int slack[maxn],vx[maxn],vy[maxn],lx[maxn],ly[maxn],p[maxn],mp[maxn][maxn];
struct data {int u,v,w;}a[maxn];
struct edge {int to,next;}e[maxn<<1]; void link(int u,int v) {
e[++cnt]=(edge){v,head[u]};head[u]=cnt;
e[++cnt]=(edge){u,head[v]};head[v]=cnt;
}
void dfs(int x) {
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x]) {
deep[e[i].to]=deep[x]+1;
fa[e[i].to]=x;
dfs(e[i].to);
}
}
bool match(int x) {
vx[x]=cnt;
for (int y=1;y<=m;y++) if (vy[y]!=cnt) {
int t=lx[x]+ly[y]-mp[x][y];
if (!t) {
vy[y]=cnt;
if (!p[y] || match(p[y])) {p[y]=x;return 1;}
}
else slack[y]=min(slack[y],t);
}
return 0;
}
int KM() {
for (int i=1;i<=m;i++) {
lx[i]=-inf;
for (int j=1;j<=m;j++) lx[i]=max(lx[i],mp[i][j]);
}
cnt=0;
for (int x=1;x<=m;x++) {
for (int i=1;i<=m;i++) slack[i]=inf;
while (1) {
int d=inf;cnt++;
if (match(x)) break;
for (int i=1;i<=m;i++) if (vy[i]!=cnt) d=min(d,slack[i]);
for (int i=1;i<=m;i++) {
if (vx[i]==cnt) lx[i]-=d;
if (vy[i]==cnt) ly[i]+=d;
}
}
}
int ans=0;
for (int i=1;i<=m;i++) ans+=mp[p[i]][i];
return ans;
}
int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) {
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
id[a[i].u][a[i].v]=id[a[i].v][a[i].u]=i;
}
for (int u,v,i=1;i<n;i++) {
scanf("%d%d",&u,&v);
link(u,v);vis[id[u][v]]=1;
}
dfs(1);memset(head,0,sizeof(head));cnt=0;
for (int i=1;i<=m;i++) if (!vis[i]) {
int x=a[i].u,y=a[i].v,w=a[i].w;
if (deep[x]<deep[y]) swap(x,y);
int t=deep[x]-deep[y];
while (t--) mp[id[x][fa[x]]][i]=max(0,a[id[x][fa[x]]].w-w),x=fa[x];
while (x!=y) {
mp[id[x][fa[x]]][i]=max(0,a[id[x][fa[x]]].w-w);
mp[id[y][fa[y]]][i]=max(0,a[id[y][fa[y]]].w-w);
x=fa[x],y=fa[y];
}
}
printf("%d",KM());
return 0;
}
【bzoj1937】 Shoi2004—Mst 最小生成树的更多相关文章
- [BZOJ1937][SHOI2004]Mst最小生成树(KM算法,最大费用流)
1937: [Shoi2004]Mst 最小生成树 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 802 Solved: 344[Submit][Sta ...
- 【KM】BZOJ1937 [Shoi2004]Mst 最小生成树
这道题拖了好久因为懒,结果1A了,惊讶∑( 口 || [题目大意] 给定一张n个顶点m条边的有权无向图.现要修改各边边权,使得给出n-1条边是这张图的最小生成树,代价为变化量的绝对值.求最小代价之和. ...
- BZOJ1937 [Shoi2004]Mst 最小生成树
首先由贪心的想法知道,树边只减不加,非树边只加不减,令$w_i$表示i号边原来的边权,$d_i$表示i号边的改变量 对于一条非树边$j$连接着两个点$x$.$y$,则对于$xy$这条路径上的所有树边$ ...
- 【BZOJ1937】[Shoi2004]Mst 最小生成树 KM算法(线性规划)
[BZOJ1937][Shoi2004]Mst 最小生成树 Description Input 第一行为N.M,其中 表示顶点的数目, 表示边的数目.顶点的编号为1.2.3.…….N-1.N.接下来的 ...
- BZOJ 1937: [Shoi2004]Mst 最小生成树 [二分图最大权匹配]
传送门 题意: 给一张无向图和一棵生成树,改变一些边的权值使生成树为最小生成树,代价为改变权值和的绝对值,求最小代价 线性规划的形式: $Min\quad \sum\limits_{i=1}^{m} ...
- [BZOJ 1937][Shoi2004]Mst 最小生成树
传送门 $ \color{red} {solution:} $ 对于每条树边\(i\),其边权只可能变小,对于非树边\(j\),其边权只可能变大,所以对于任意非树边覆盖的树边有 \(wi - di & ...
- MST最小生成树
首先,贴上一个很好的讲解贴: http://www.wutianqi.com/?p=3012 HDOJ 1233 还是畅通工程 http://acm.hdu.edu.cn/showproblem.ph ...
- [poj1679]The Unique MST(最小生成树)
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 28207 Accepted: 10073 ...
- UVA 1151 Buy or Build (MST最小生成树,kruscal,变形)
题意: 要使n个点之间能够互通,要使两点直接互通需要耗费它们之间的欧几里得距离的平方大小的花费,这说明每两个点都可以使其互通.接着有q个套餐可以选,一旦选了这些套餐,他们所包含的点自动就连起来了,所需 ...
随机推荐
- 文字排版 - bootStrap4常用CSS笔记
[文字常用标签] <h1>.<h2>.<h3>.<h4>.<h5>.<h6> 标题类标签,h1字体最大以次类推 <sm ...
- 浅谈C与Java
Java的方法调用过程 Java变量:基本类型变量.指针变量 push 压入新的栈桢 在栈桢内部创建局部基本类型变量,接收参数值 在栈桢内部创建局部指针变量,接收参数值后,该指针变量指向堆上实例 po ...
- docker 下载安装与配置
# mac离线安装dockerhttps://download.docker.com/mac/stable/24312/Docker.dmg # windows离线安装dockerhttp://mir ...
- Python数据分析工具库-Numpy 数组支持库(二)
1 shape变化及转置 >>> a = np.floor(10*np.random.random((3,4))) >>> a array([[ 2., 8., 0 ...
- 【转】Java生成plist下载ipa文件
我们在上传ipa想要安装的时候必须要通过plist文件去下载,并且还要遵循 itms-services协议. 意思就是,第一步我们要生成一个plist文件, 第二步生成一个html文件,用来指向pli ...
- 调试存储过程:ORA-0131 Insufficient privileges
http://www.cnblogs.com/empty01/p/5568250.html
- Beta阶段版本控制报告
版本控制代码及文档要求 在coding.net版本控制; 公开项目,教师.专家.其他同学可以不注册源代码.在此公布git地址. 报告beta阶段2周中,项目的版本控制情况,不包括未在coding.ne ...
- 欢迎来怼--第二十九次Scrum会议
一.小组信息 队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 小组照片 二.开会信息 时间:2017/11/17 15:55~16:25,总计30min. 地 ...
- 暑假作业app博客
一.光照传感器 界面 简介 运用了传感器类,通过手机的感应区根据当时的光照强度显示出数据. 核心代码 protected void onCreate(Bundle savedInstanceState ...
- 团队作业4Alpha冲刺(真.三英战吕布团队)
第一天 2018/6/13 1.1 今日完成任务情况以及遇到的问题. 1.1.1:完成前台部分界面优化,后台进行代码优化 1.1.2团队前台部分js.jquery部分功能实现有难度. 1.2 明天任务 ...