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,选入 ...
随机推荐
- SqlServer_存储过程
1.查询全部数据 create proc stu1 as begin select * from Students end go exec stu1 2.根据姓名查询信息 --存储过程内部自带值cre ...
- 委托(作用:解耦),lambda的演化
1.了解委托 MyDelegate类代码如下: using System; using System.Collections.Generic; using System.Linq; using Sys ...
- Javascript入门(五)数组操作、循环语句
一.数组与数组操作 <script type="text/javascript"> //数组定义方式 var list1 = new Array(1,2,3); var ...
- mysql 原理 ~ redo
一 简介:redo log二 文件 ib_logfile0 ib_logfile1 两个redo log 默认为一组 循环覆盖写入三 相关参数 innodb_log_file_size=256 ...
- 调整JVM虚拟机的内存大小
jvm默认只有64M; public static void main(String[] args){ byte b[] = new byte[1024*1024*65];//此时会报内存溢出: } ...
- linux中如何使用终端裁剪图片?
1,首先要安装支持图片裁剪的包: sudo apt-get install imagemagick 需要的话可以update一下, 2,在图片所在位置打开终端,我的我的截图叫screenshot.pn ...
- Django中的csrf基础了解
简介 django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成.而对于django中设置防跨站请求伪造功能有 ...
- python基础-----异常问题
---恢复内容开始--- 当发生python不知所措的错误时,python会创建一个异常对象, 如果你编写处理该异常的代码,程序将会继续运行: 如果你未对异常做任何处理,程序将会停止,并显示一个tra ...
- java在进程启动和关闭.exe程序
/** * @desc 启动进程 * @author zp * @date 2018-3-29 */ public static void startProc(String processName) ...
- laravel 关闭 csrf 验证 TokenMismatchException
csrf验证失败 注释掉kernel.php 的 csrf 行代码