bzoj1937: [Shoi2004]Mst 最小生成树
也是神了。感觉一天都在好神的题里面游荡。
本来是想复习一下KM的,结果一眼过去???
结果做法是这样的,把树边和非树边分成两个集合
根据贪心的思想,要搞的话肯定树边减少,而非树边增加。
对于在原树中的一条边的两点x,y,如果在最小生成树里面x到y的那一条路径的边有比这条边大的,那我们肯定得做点什么。
抽象就是这样wi+di>=wj-dj wi是原树的边权,wj最小生成树路径上的边权,d是我们人为的改变。
变形一下 ---> di+dj>=wj-wi 其中wj和wi已知。 。。。。顶标??(原谅我以前没有理性的理解这个算法)被秀飞
感觉有点差分约束的味道??然后构图我也觉得很难。。。
先把最小生成树遍历一次,然后再枚举非树边两个点往上跳
感觉我跑的挺慢的。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std;int n; struct sc {int x,y,d; }e[21000];int mp[1100][1100]; bool istree[21000]; struct node {int x,y,d,id,next; }a[21000];int len,last[21000]; void ins(int x,int y,int d,int id) {len++;a[len].x=x;a[len].y=y;a[len].d=d;a[len].id=id;a[len].next=last[x];last[x]=len; } int fa[1100],dep[1100],pre[11000]; void dfs(int x,int fr) {for(int k=last[x];k;k=a[k].next){int y=a[k].y;if(y!=fr){fa[y]=x;dep[y]=dep[x]+1;pre[y]=k;dfs(y,x);}} } int love[1100][1100]; void build(int now,int i) {int x=e[i].x,y=e[i].y;while(x!=y){if(dep[x]>dep[y])swap(x,y);int k=pre[y];love[now][a[k].id]=a[k].d-e[i].d;y=fa[y];} }int exg[1100],exb[1100]; bool vg[1100],vb[1100]; int match[1100],need[1100]; bool findboy(int x) {vg[x]=true;for(int i=1;i<=n;i++){if(vb[i]==false){int gap=exg[x]+exb[i]-love[x][i];if(gap==0){vb[i]=true;if(match[i]==0||findboy(match[i])==true){match[i]=x;return true;}}else need[i]=min(need[i],gap);}}return false; } void KM() {memset(match,0,sizeof(match));memset(exg,0,sizeof(exg));memset(exb,0,sizeof(exb));for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)exg[i]=max(exg[i],love[i][j]);for(int i=1;i<=n;i++){memset(need,63,sizeof(need));while(1){memset(vg,false,sizeof(vg));memset(vb,false,sizeof(vb));if(findboy(i)==true)break;int d=2147483647;for(int j=1;j<=n;j++)if(vb[j]==false)d=min(d,need[j]);for(int j=1;j<=n;j++){if(vg[j]==true)exg[j]-=d;if(vb[j]==true)exb[j]+=d;else need[j]-=d;}}}int ans=0;for(int i=1;i<=n;i++)ans+=love[match[i]][i];printf("%d\n",ans); } int main() {freopen("mst.in","r",stdin);freopen("mst.out","w",stdout);int m,x,y,d;scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].d);mp[e[i].x][e[i].y]=i;}memset(istree,false,sizeof(istree));for(int i=1;i<n;i++){scanf("%d%d",&x,&y);int id=mp[x][y];istree[id]=true;ins(x,y,e[id].d,i);ins(y,x,e[id].d,i);}dep[1]=1;dfs(1,0);memset(love,0,sizeof(love));for(int i=1,tp=0;i<=m;i++)if(istree[i]==false)build(++tp,i);n=max(n-1,m-(n-1));KM();return 0; }
转载于:https://www.cnblogs.com/AKCqhzdy/p/8651292.html
bzoj1937: [Shoi2004]Mst 最小生成树相关推荐
- 【KM】BZOJ1937 [Shoi2004]Mst 最小生成树
这道题拖了好久因为懒,结果1A了,惊讶∑( 口 || [题目大意] 给定一张n个顶点m条边的有权无向图.现要修改各边边权,使得给出n-1条边是这张图的最小生成树,代价为变化量的绝对值.求最小代价之和. ...
- BZOJ 1937: [Shoi2004]Mst 最小生成树 [二分图最大权匹配]
传送门 题意: 给一张无向图和一棵生成树,改变一些边的权值使生成树为最小生成树,代价为改变权值和的绝对值,求最小代价 线性规划的形式: $Min\quad \sum\limits_{i=1}^{m} ...
- UVA 1151 Buy or Build MST(最小生成树)
题意: 在平面上有n个点,要让所有n个点都连通,所以你要构造一些边来连通他们,连通的费用等于两个端点的欧几里得距离的平方.另外还有q个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相 ...
- MST(最小生成树)的构造
是什么: 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. kruskal算法: #include<iostream> ...
- MST(最小生成树)上的确定性和存在性问题
题目1: 给定一个n个点m条边的连通图,保证没有自环和重边.对于每条边求出,在其他边权值不变的情况下,它能取的最大权值,使得这条边在连通图的所有最小生成树上.假如最大权值为无限大,则输出-1. 题解: ...
- 【恋上数据结构】图代码实现、最小生成树(Prim、Kruskal)、最短路径(Dijkstra、Bellman-Ford、Floyd)
图 最小生成树(Minimum Spanning Tree) Prim算法 切分定理 Prim算法 – 执行过程 Prim算法 – 代码实现 Kruskal算法 Kruskal算法 – 执行过程 Kr ...
- prim最小生成树算法 邻接表+STL实现
一.预备知识 优先队列 二.代码: #include<iostream> #include<list> #include<vector> #include<m ...
- 求的带权图最小生成树的Prim算法和Kruskal算法
求的带权图最小生成树的Prim算法和Kruskal算法 最小生成树的概念 最小生成树其实是最小权重生成树的简称. 一个连通图可能有多个生成树.当图中的边具有权值时,总会有一个生成树的边的权值之和小于或 ...
- Java实现最小生成树算法(Prim算法)
Prim算法 Prim算法,每一步都会为一颗生长中的树添加一条边.一开始这棵树只有一个顶点,然后哦会向它添加V-1条边,每次总是将下一条连接树的顶点与不在树中且权重最小的边加入树中 实现 最小生成树的 ...
最新文章
- CentOS 7最小安装之后应该尽快做好的几件事情
- Cloud Foundry 登录 Azure,一键快速部署 PaaS
- Prometheus — 软件架构
- 【Android Gradle 插件】Extension 扩展类型 ( Module 引入插件类型 | application 插件 | library 插件 | Variants 变体列表 )
- IDEA使用指南常用快捷键
- 看YYModel源码的一些收获
- java限制金额控制_JavaMail 限额管理
- java实现调查问卷_智能办公进行时丨富士施乐邀您参与有奖问卷调查
- 8.Springcloud的Feign嵌入Ribbon实现接口式调用(改变restTemplate和Ribbon的调用方式)...
- CentOS7图形界面模式
- Unity使用FGUI的基本操作(一)
- 今天把中国建设银行APP4.2.1版iOS客户端里所有的功能都点了一遍
- 计算机里的文案怎么设置背景,如何将图片设置为Word文档的背景
- 小众绿软|媒体:Soprano Audio Player v1.60
- FigDraw 11. SCI 文章绘图之小提琴图 (ViolinPlot)
- html5 足球比赛阵容图,HTML5/Velocity.js 3D足球阵容
- 网络攻击与防御技术期中习题
- 利用ruby演示程序执行
- 【Ubuntu】Ubuntu常见优化设置
- 如何在python中表示微分_Python实现自动微分(Automatic Differentiation)