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,选入 ...
随机推荐
- Linux之vi编辑器的使用
今天我们来说一下vi编辑器的使用,vi编辑器主要用来在Linux环境下编辑配置文件. 一.使用方法: 1.输入命令 vi filename,打开文件,处于一个查看模式 2.点击键盘 i,进入inser ...
- 【CentOS】JDK的安装
FTP文件上传方式(推荐) # 解压 tar zxvf jdk-9_linux-x64_bin.tar.gz # 修改profile文件 sudo vi /etc/profile # 在文件结尾添加如 ...
- MySQL基本命令(待更新...)
数据库操作SQL语句 show databases; 表操作SQL语句 数据库权限操作SQL语句 参考链接 :http://www.cnblogs.com/bzys/archive/2013/01/2 ...
- Kotlin中三元运算符
int a = 10;int b = 11;int c = a > b ? a : b; 到了 kotlin中 val a = 10val b = 11val c = if (a > b) ...
- Git——如何将本地项目提交至远程仓库
参考文章:http://blog.csdn.net/dadaxiongdebaobao/article/details/52081826 git 将一个本地文件目录提交到远程仓库的步骤 参考文章: ...
- JAVA百度过的异常(1)
1.---无法解析类型 javax.servlet.http.HttpServletRequest.从必需的 .class 文件间接引用了它 The type javax.servlet.http.H ...
- jQuery单选框的回显
代码示例: html: <div class="col-lg-4"> <label class="radio-inline"> < ...
- 为共享服务器配置Oracle数据库
参考资料 https://docs.oracle.com/cd/E11882_01/server.112/e25494/manproc.htm#ADMIN00502
- 【VMware vSphere】Veeam备份
前言 刚刚整理自己的Onenote笔记,发现有一篇笔记没有整理到博客上面来.因为没有许可证书,所以最后也没有成功,但是还是写在这里吧,万一哪儿天有了许可证书就又可以做试验了~ Veeam Backup ...
- 记录 一次深夜救火:datanode.data.dir
火灾背景: Hadoop集群,4个节点,每一台配置都不一样 火灾现场: 1.突然发现DN4硬盘报警,检查硬盘,发现挂载如下: /home 200GB /home/data 3TB 然后发现datano ...