最小树形图的路径是在不断建立新图的过程中更新的,因此需要开一个结构体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 最小树形图+路径记录更新的更多相关文章

  1. Codeforces 240E. Road Repairs 最小树形图+输出路径

    最小树形图裸题,只是须要记录路径 E. Road Repairs time limit per test 2 seconds memory limit per test 256 megabytes i ...

  2. CF240E Road Repairs(最小树形图-记录路径)

    A country named Berland has n cities. They are numbered with integers from 1 to n. City with index 1 ...

  3. codeforce 240E

    /* 最小树形图+保存路径 第一次想错了,各种wa,tle后网上看资料,找到一篇错误的题解... 最后用对着正解分析了一波,感觉对最小树形图又有了新的理解:最小树形图的精髓在于每张图更新的时间信息! ...

  4. HDU 4966 GGS-DDU(最小树形图)

    n个技能,每个技能有0-a[i]的等级,m个课程,每个课程需要前置技能c[i]至少达到lv1[i]等级,效果是技能d[i]达到lv2[i]等级,花费w[i]. 输出最小花费使得全技能满级(初始全技能0 ...

  5. 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 ...

  6. UVA 11865 Stream My Contest(最小树形图)

    题意:N台机器,M条有向边,总资金C,现要到搭建一个以0号机(服务器)为跟的网路,已知每条网线可以把数据从u传递到v,其带宽为d,花费为c,且d越大,传输速度越快,问能够搭建的传输速度最快的网络d值是 ...

  7. 【UVA 11865】 Stream My Contest (二分+MDST最小树形图)

    [题意] 你需要花费不超过cost元来搭建一个比赛网络.网络中有n台机器,编号0~n-1,其中机器0为服务器,其他机器为客户机.一共有m条可以使用的网线,其中第i条网线的发送端是机器ui,接收端是机器 ...

  8. hdu2121 最小树形图的虚根

    /* 最小树形图的第二题,终于有了一些理解 具体看注释 */ /* 无定根的最小树形图 建立虚root 每次只找最短的那条入边 最小树形图理解: 第一步:寻找最短弧集E:扫一遍所有的边,找到每个点权值 ...

  9. 最小树形图——朱刘算法(Edmonds)

    定义:一个有向图,存在从某个点为根的,可以到达所有点的一个最小生成树,则它就是最小树形图. 朱刘算法实现过程: [在选出入边集后(看步骤1),若有向图中不存在有向环,说明该图就是最小树形图] 1,选入 ...

随机推荐

  1. tomcat线程一直处于RUNNABLE,不接受请求

    最近项目中一个模块出现一个问题,本人做的比较浅显,所以很简单的问题一直搞了好几天,通过各种查资料.工具终于分析除了问题.问题如下: 现在对tomcat一个工程(会通过httpurlconnection ...

  2. java知识点2

    进阶篇 Java底层知识 字节码.class文件格式 CPU缓存,L1,L2,L3和伪共享 尾递归 位运算 用位运算实现加.减.乘.除.取余 设计模式 了解23种设计模式 会使用常用设计模式 单例.策 ...

  3. Python全栈(第一部分)day3

    昨日内容回顾 格式化输出 %s %d %% 编码 ascii: 只能显示英文,特殊字符,数字 万国码unicode: 最开始16位,中文不够,用32位,占用4个字节 升级: utf-8 utf-16 ...

  4. Maya API Test

    import maya.OpenMaya as OpenMaya import maya.OpenMayaMPx as OpenMayaMPx sl = OpenMaya.MSelectionList ...

  5. DevExpress VCL 的 cxDBTreeList 的使用方法

    DevExpress VCL 的 cxDBTreeList 的使用方法:(假设控件名为: WBSTree) 1.控件WBSTree 通过绑定  DataSet 获取数据记录(Nodes),通过 Col ...

  6. python zip文件压缩和解压

    压缩 import shutil zipOutputName = "1234" # 输出1234.zip fileType = "zip" # 文件类型zip ...

  7. HTTP协议06-报文首部

    HTTP报文格式 ​ HTTP协议的请求和响应报文中必定包含HTTP首部.首部内容为客户端和服务器分别处理请求和响应提供所需要的信息. 1)HTTP请求报文 在请求中,HTTP报文由方法.URI.HT ...

  8. C++ URLencode library

    I need a library that can URLencode a string/char array. Now, I can hex encode an ASCII array like h ...

  9. 题解-CodeForces835F Roads in the Kingdom

    Problem CodeForces-835F 题意:求基环树删去环上任意一边后直径最小值,直径定义为所有点对最近距离的最大值 Solution 首先明确删去环上一点是不会影响树内直径的,所以应当先把 ...

  10. Equivalent Sets HDU - 3836 2011多校I tarjan强连通分量

    题意: 给一些集合 要求证明所有集合是相同的 证明方法是,如果$A∈B$,$B∈A$那么$A=B$成立 每一次证明可以得出一个$X∈Y$ 现在已经证明一些$A∈B$成立 求,最少再证明多少次,就可以完 ...