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,选入 ...
随机推荐
- VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNTION(翻译)
0 - ABSTRACT 在这个工作中,我们研究了卷积网络的深度对于它在大规模图像识别设置上的准确率的效果.我们的主要贡献是对使用非常小的卷积核(3×3)来增加深度的网络架构进行彻底评估,这说明了通过 ...
- 微信小程序获取手机验证码
一种比较常见的功能获取手机验证码 先看效果图: 其实这个功能实现起来很简单,主要就是调取第三方接口,拿到返回值验证的问题 直接上代码吧: wxml页面: <view class='changeI ...
- Django 基于类的通用视图
在早期,我们认识到在视图开发过程中有共同的用法和模式.这时我们引入基于函数的通用视图来抽象这些模式以简化常见情形的视图开发. 基于函数视图的用法有以下三种: def index(request): r ...
- html超文本标记语言基础一
1,基本格式 <!DOCTYPE html> //声明为 HTML5 文档 <html> <head> <meta charset="utf-8&q ...
- SpringBoot--配置详解
SpringBoot使用了一个全局的配置文件application.properties,放在src/mian/resource目录下或者类路径的/config下.springboot的全局配置文件的 ...
- linux+php实现定时任务[链接]
1.crontab 详细用法 定时任务 https://www.cnblogs.com/aminxu/p/5993769.html 2.查看crontab日志 https://www.cnblogs. ...
- 最近邻算法(KNN)
最近邻算法: 1.什么是最近邻是什么? kNN算法全程是k-最近邻算法(k-Nearest Neighbor) kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数数以一个类型别 ...
- Keepalived详解(四):通过vrrp_script实现对集群资源的监控【转】
一.通过vrrp_script实现对集群资源的监控: Keepalived基础HA功能时用到了vrrp_script这个模块,此模块专门用于对集群中服务资源进行监控.与此模块一起使用的还有track_ ...
- TCP、消息分包和协议设计
TCP是一种流式协议 TCP是一种面向连接的.可靠的.基于字节流的传输层通信协议. 流式协议的特点是什么?就像流水连续不断那样,消息之间没有边界.例如send了3条消息(这里的“消息”是指应用层的一个 ...
- OpenStack实践系列②认证服务Keystone
OpenStack实践系列②认证服务Keystone 三.实战OpenStack之控制节点3.1 CentOS7的时间同步服务器chrony 下载chrony # yum install -y chr ...