codeforce 240E 最小树形图+路径记录更新
最小树形图的路径是在不断建立新图的过程中更新的,因此需要开一个结构体cancle记录那些被更新的边,保存可能会被取消的边和边在旧图中的id
在朱刘算法最后添加了一个从后往前遍历新建边的循环,这可以理解为回溯,通过cancle结构体不断找到上一个时间点更新的边id,并且取消那些被代替的边
至于为什么要按建图时间从后往前回溯,我在下面举了一个例子:

上图取自朱刘算法标准示例,最小树形图路径保存与更新
拿节点v3举例
指向v3的边有三条:a4,a13,a9
第一次循环:步骤1,2建立最短弧集:a4被保存在最短弧集E中,usedE[4]=1
步骤3:准备新建图,此时a9,a13权值被更新,其旧id被保存在cancle.id中,a4的id被保存在cancle.pre中,假设a9,a13被赋予新id a16,a17
第二次循环:步骤1, 2建立新图:a17被保存在新图中,usedE[17]=1
步骤3:准备建立新图,a16被更新,假设其被赋予新id a18
第三次循环:没有环了,退出循环
退出循环后从后往前便利新建边,依旧拿v3举例
首先是循环到usedE[17]:cancle[17].id=13,因此usedE[13]=1
cancle[17].pre=4,因此usedE[4]=0
最后在遍历被使用边时,可以发现被使用的是边a13,而a4被a13代替了
大家也可以拿其余点自己试试,下面贴上我的代码,codeforce240E,输入输出有点坑,需要从通过文件io
#include<iostream>
#include<cstring>
#include<cstdio>
#define MAXN 100005
#define MAXM MAXN*20
#define INF 0x3f3f3f3f
using namespace std;
struct Edge{
int u,v,cost;
int w;//原始权值
int id;
}edge[MAXM];
inline void addedge(int u,int v,int cost,int w,int id){
edge[id].cost=edge[id].w=cost;
edge[id].u=u;
edge[id].v=v;
edge[id].id=id;
}
struct Cancle{//
int pre;//保存可能被取消的那条边的id
int id;//保存可能新增的那条边更新前的id
}cancle[MAXM];
int pre[MAXN],id[MAXN],vis[MAXN],in[MAXN];
int preid[MAXN],usedE[MAXN];
int zhuliu(int root,int n,int m){
int res=,total=m;//total是下一条新建边的id
while(){
for(int i=;i<n;i++) in[i]=INF;
for(int i=;i<m;i++)
if(edge[i].u!=edge[i].v && edge[i].cost<in[edge[i].v]){
pre[edge[i].v]=edge[i].u;
in[edge[i].v]=edge[i].cost;
//更新被加入到边集E的那条边的id
preid[edge[i].v]=edge[i].id;
}
for(int i=;i<n;i++)
if (i!=root && in[i]==INF) return -; int tn=;
memset(id,-,sizeof id);
memset(vis,-,sizeof vis);
in[root]=;
for(int i=;i<n;i++){
res+=in[i];
int v=i;
///将新图中被使用到的边保存
if(i!=root) usedE[preid[i]]++;
while(v!=root && vis[v]!=i && id[v]==-){
vis[v]=i;
v=pre[v];
}
if(v!=root && id[v]==-){
for(int u=pre[v];u!=v;u=pre[u])
id[u]=tn;
id[v]=tn++;
}
}
if(tn==) break;
for(int i=;i<n;i++)
if(id[i]==-) id[i]=tn++;
for(int i=;i<m;i++){
int v=edge[i].v;
edge[i].u=id[edge[i].u];
edge[i].v=id[edge[i].v];
if(edge[i].u!=edge[i].v){
edge[i].cost-=in[v];
//把这条边的更新信息保存一下
cancle[total].id=edge[i].id;//注意,这里是保留该边更新前的id!
cancle[total].pre=preid[v];//原本指向v的边被取消了
edge[i].id=total++;
}
}
n=tn;
root=id[root];
}
/*
为什么要从后往前?
*/
for(int i=total-;i>=m;i--)
if(usedE[i]){
usedE[cancle[i].pre]--;
usedE[cancle[i].id]++;
}
return res;
}
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
int n,m;
scanf("%d%d",&n,&m); int u,v,w;
for(int i=;i<m;i++){
scanf("%d%d%d",&u,&v,&w);
u--,v--;
addedge(u,v,w,w,i);
} int root=;
int res=zhuliu(root,n,m);
if(res==||res==-)
printf("%d\n",res);
else{
printf("%d\n",res);
for(int i=;i<m;i++)
if(usedE[i]&&edge[i].w) printf("%d ",i+);
}
printf("\n"); return ;
}
这段代码挂在了test31.。不知道为什么,望大佬指正,非常感谢!
codeforce 240E 最小树形图+路径记录更新的更多相关文章
- Codeforces 240E. Road Repairs 最小树形图+输出路径
最小树形图裸题,只是须要记录路径 E. Road Repairs time limit per test 2 seconds memory limit per test 256 megabytes i ...
- CF240E Road Repairs(最小树形图-记录路径)
A country named Berland has n cities. They are numbered with integers from 1 to n. City with index 1 ...
- codeforce 240E
/* 最小树形图+保存路径 第一次想错了,各种wa,tle后网上看资料,找到一篇错误的题解... 最后用对着正解分析了一波,感觉对最小树形图又有了新的理解:最小树形图的精髓在于每张图更新的时间信息! ...
- HDU 4966 GGS-DDU(最小树形图)
n个技能,每个技能有0-a[i]的等级,m个课程,每个课程需要前置技能c[i]至少达到lv1[i]等级,效果是技能d[i]达到lv2[i]等级,花费w[i]. 输出最小花费使得全技能满级(初始全技能0 ...
- HDU 2121 Ice_cream’s world II 不定根最小树形图
题目链接: 题目 Ice_cream's world II Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- UVA 11865 Stream My Contest(最小树形图)
题意:N台机器,M条有向边,总资金C,现要到搭建一个以0号机(服务器)为跟的网路,已知每条网线可以把数据从u传递到v,其带宽为d,花费为c,且d越大,传输速度越快,问能够搭建的传输速度最快的网络d值是 ...
- 【UVA 11865】 Stream My Contest (二分+MDST最小树形图)
[题意] 你需要花费不超过cost元来搭建一个比赛网络.网络中有n台机器,编号0~n-1,其中机器0为服务器,其他机器为客户机.一共有m条可以使用的网线,其中第i条网线的发送端是机器ui,接收端是机器 ...
- hdu2121 最小树形图的虚根
/* 最小树形图的第二题,终于有了一些理解 具体看注释 */ /* 无定根的最小树形图 建立虚root 每次只找最短的那条入边 最小树形图理解: 第一步:寻找最短弧集E:扫一遍所有的边,找到每个点权值 ...
- 最小树形图——朱刘算法(Edmonds)
定义:一个有向图,存在从某个点为根的,可以到达所有点的一个最小生成树,则它就是最小树形图. 朱刘算法实现过程: [在选出入边集后(看步骤1),若有向图中不存在有向环,说明该图就是最小树形图] 1,选入 ...
随机推荐
- 传统javaweb 改成 Maven项目
1. 项目右键-- Configure --Convert to Maven Project 后可以生成maven结构,多了红色框的 <project xmlns="http:/ ...
- Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields(理解)
0 - 人体姿态识别存在的挑战 图像中的个体数量.尺寸大小.位置均未知 个体间接触.遮挡等影响检测 实时性要求较高,传统的自顶向下方法运行时间随着个体数越多而越长 1 - 整体思路 整个模型架构是自底 ...
- 基于html + css 实现图片瀑布流
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- 安装mysql8.0.12以及修改密码和Navicat的连接
mysql8.0+与安装其他版本不同一.安装mysql8.0.121.到官网https://www.mysql.com/ 下载mysql-8.0.12-winx64.zip(不要.mis),直接解压 ...
- JavaScript-DOM(重点)
解析过程 DOM树(一切皆是节点) DOM可以做什么 清楚DOM的结构 获取其它DOM(事件源)的三种方式 事件 事件的三要素 绑定事件的方式 JavaScript入口函数 window.onload ...
- boost.asio包装类st_asio_wrapper开发教程(2013.12.8更新)(二)
如果你是偶然浏览到这里,请先看 源代码及例程下载地址:命令行:svn checkout http://st-asio-wrapper.googlecode.com/svn/trunk/ st-asio ...
- 范围for语句
C++11 新标准引入了一种更简单的for语句,这种语句可以遍历容器或其他序列的所有元素.范围for语句(range for statement)的语法形式是: for (declaration : ...
- kafka组件makemirror处理跨机房业务的应用
业务背景:app分散在不同的idc厂商不同的地域,产生业务数据都向一个kafka中进行处理,这些数据比较分散,如果一时网络抖动或者其他因素,数据就丢失了app --> kafka --> ...
- 设计模式--观察者模式Observer(对象行为型)
一.观察者模式 观察者模式是在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新.观察者模式也被称之为:主题-观察者模式,发布-订阅模式,前者是一,后者是多. ...
- [转]ASCII码表及扩展ASCII码表,方便查阅
ASCII码表可以看成由三部分组成: 第一部分:由00H到1FH共32个,一般用来通讯或作为控制之用.有些可以显示在屏幕上,有些则不能显示,但能看到其效果(如换行.退格).如下表: 第二部分:是由20 ...