题目大意

给你\(n\)个文件的关系,求出某一个点,这个点到叶节点的长度的总距离最短。(相对长度的定义在题目上有说明)

感想

吐槽一下出题人,为什么出的题目怎么难看懂,我看了整整半个小时,才看懂。

题解

首先数据给我们的是一棵树,一开始我审题不仔细以为是到每个节点的距离最短,就以为是要求树的重心。后来发现不对,而且节点之间的距离不怎么好处理,因为以不同的节点为起点,两节点之间的距离是会变化的。需要用树形dp来解决这个问题,首先预处理出以\(u\)为根节点的子树中有多少个叶节点,因为每一个相对路径的结尾都是没有\(/\)符号的,方便我们计算长度,还要预处理出每一个节点到根节点的长度,因为这个长度是一定的,算出来还是方便计算答案。还有一个是整棵树一共有多少个叶节点,因为在我们计算的节点的上方和下方的计算方法是不一样的。
那么我们树形dp定义状态为\(f[v]\)表示以\(v\)为根节点的最小相对距离之和。
核心的转移方程也是非常好理解的:\(f[v]=f[u]-(len[v]+1)*sz[v]+3*(sum-sz[v])\),解释一下:\(u\)为\(v\)的父亲,为什么是从父亲转移到儿子而不是从儿子转移到父亲?因为越靠近根节点的答案和根节点的答案越接近,每次更改只有一个文件的名字,所以我们先转移到儿子。我们考虑一下,每次我们从父亲节点转移到儿子节点,那么儿子节点以下所有叶子节点都会因为起始节点的改变而减少答案,这个减少的答案是\((len[v]+1)\times sz[v]\),什么意思?因为每次都有一个/号,还有一个\(v\)号字符串的长度,这些答案对于每一个叶子节点都会产生减少。同理在\(v\)节点的另外一侧,也就是\(v\)以上的子树,我们会因为其实节点的降低而增加一段的答案,也就是\(3\times(sum-sz[v])\),\(sum-sz[v]\)表示的是另一半子树中叶节点的个数,\(3\)是因为\(../\)的长度是\(3\),那么转移方程就得到了。

ac代码

# include <cstdio>
# include <cstring>
# include <algorithm>
# include <ctype.h>
# include <iostream>
# include <cmath>
# include <map>
# include <vector>
# include <queue>
# define LL long long
# define ms(a,b) memset(a,b,sizeof(a))
# define ri (register int)
# define inf (0x7f7f7f7f)
# define pb push_back
# define fi first
# define se second
# define pii pair<int,int>
# define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
using namespace std;
inline int gi(){
    int w=0,x=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return w?-x:x;
}
inline LL gll(){
    LL w=0,x=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return w?-x:x;
}
# define N 200005
struct edge{
    int to,nt;
}E[N<<1];
LL H[N],len[N],f[N],sz[N],dis[N];
int cnt,sum,n;
LL ans;
bool isleaf[N];
void addedge(int u,int v){
    E[++cnt]=(edge){v,(int)H[u]}; H[u]=cnt;
}
void dfs1(int u){
    for (int e=H[u];e;e=E[e].nt){
        int v=E[e].to;
        dis[v]=dis[u]+len[v]+1; //+1是因为每一次文件之间都有一个/
        dfs1(v); sz[u]+=sz[v];
    }
    if (isleaf[u]) sz[u]=1,dis[u]--,f[1]+=dis[u];//如果是叶节点那么就之间算就可以了
}
void dfs2(int u){
    for (int e=H[u];e;e=E[e].nt){
        int v=E[e].to;
        if (isleaf[v]) continue;
        f[v]=f[u]-(len[v]+1)*sz[v]+3*(sum-sz[v]);//转移方程
        ans=min(ans,f[v]);
        dfs2(v);
    }
}
int main(){
//  File("DirectoryTraversal");
    n=gi();
    for (int i=1;i<=n;i++){
        char s[20]; scanf("%s",s); len[i]=strlen(s);
        int m=gi();
        if (m==0) sum++,isleaf[i]=1;
        for (int j=1;j<=m;j++){
            LL id=gll();
            addedge(i,id);
        }
    }
    dfs1(1); ans=f[1]; dfs2(1);
    printf("%lld\n",ans);
    return 0;
}

[luogu4268][bzoj5195][USACO18FEB]Directory Traversal的更多相关文章

  1. 【常见Web应用安全问题】---4、Directory traversal

    Web应用程序的安全性问题依其存在的形势划分,种类繁多,这里不准备介绍所有的,只介绍常见的一些.  常见Web应用安全问题安全性问题的列表: 1.跨站脚本攻击(CSS or XSS, Cross Si ...

  2. Web for pentester_writeup之Directory traversal篇

    Web for pentester_writeup之Directory traversal篇 Directory traversal(目录遍历) 目录遍历漏洞,这部分有三个例子,直接查看源代码 Exa ...

  3. luogu4268 Directory Traversal (dfs)

    题意:给一个树状的文件结构,让你求从某个文件夹出发访问到所有文件,访问路径字符串长度之和的最小值,其中,访问父节点用..表示,两级之间用/分割 做两次dfs,第一次算DownN[x]和DownS[x] ...

  4. bzoj 5195: [Usaco2018 Feb]Directory Traversal【树形dp】

    注意到目录是一颗树结构,然后就简单了,预以1为根的处理出dis[u]为以这个点为根,到子树内的目录总长,si为子树内叶子数 第二遍dfs换根即可 #include<iostream> #i ...

  5. Directory traversal

    Find the hidden section of the photo galery. 找到相册的隐藏部分. 直接能够目录遍历: 虽然galerie禁止访问,但是密码就在里面----直接爆破或者爬虫 ...

  6. Spring框架中文件目录遍历漏洞 Directory traversal in Spring framework

    官方给出的描述是Spring框架中报告了一个与静态资源处理相关的目录遍历漏洞.某些URL在使用前未正确加密,使得攻击者能够获取文件系统上的任何文件,这些文件也可用于运行SpringWeb应用程序的进程 ...

  7. USACO比赛题泛刷

    随时可能弃坑. 因为不知道最近要刷啥所以就决定刷下usaco. 优先级排在学习新算法和打比赛之后. 仅有一句话题解.难一点的可能有代码. 优先级是Gold>Silver.Platinum刷不动. ...

  8. 前端学HTTP之web攻击技术

    前面的话 简单的HTTP协议本身并不存在安全性问题,因此协议本身几乎不会成为攻击的对象.应用HTTP协议的服务器和客户端,以及运行在服务器上的Web应用等资源才是攻击目标.本文将详细介绍攻击web站点 ...

  9. web安全性测试用例

    建立整体的威胁模型,测试溢出漏洞.信息泄漏.错误处理.SQL 注入.身份验证和授权错误. 1.   输入验证 客户端验证 服务器端验证(禁用脚本调试,禁用Cookies) 1.输入很大的数(如4,29 ...

随机推荐

  1. [Spark][Hive][Python][SQL]Spark 读取Hive表的小例子

    [Spark][Hive][Python][SQL]Spark 读取Hive表的小例子$ cat customers.txt 1 Ali us 2 Bsb ca 3 Carls mx $ hive h ...

  2. scikit-learn的线性回归模型

    来自 http://blog.csdn.net/jasonding1354/article/details/46340729 内容概要 如何使用pandas读入数据 如何使用seaborn进行数据的可 ...

  3. 如何打造网站克隆、仿站工具(C#版)

    前两天朋友叫我模仿一个网站,刚刚开始,我一个页面一个页面查看源码并复制和保存,花了我很多时间,一个字“累”,为了减轻工作量,我写了个网站“克隆工具”,一键克隆,比起人工操作, 效率提高了200%以上, ...

  4. QT 遇到的问题

    遇到的问题: 1:在QT中使用opengl,发现一个很神奇的问题,个人感觉是qt的bug. 问题详情:在我添加了一个成员变量之后,使用opengl编写的窗口没有任何输出了,只有一个背景. 但是删除那个 ...

  5. MRT与MRTS工具官宣退休,推荐使用HEG

    今天错误的删除搞丢了之前下载的MRT与MRTS工具,浏览Modis官网下载时发现找不到了,后来在其官网上发现了这则通知,原来早已停止更新的MRT这次彻底退修了.通知原文如下~~~ The downlo ...

  6. mysql操作命令梳理(4)-中文乱码问题

    在平时的mysql运维操作中,经常会碰到插入中文字段后出现乱码的情况,产生中文乱码的原因一般有:1)mysql的编码格式不对,是latin1编码.强烈推荐将mysql下的编码格式都改为utf8,因为它 ...

  7. 线上mongodb 数据库用户到期时间修改的操作记录

    登陆版权数据库,显示"此用户已到期",数据库使用的是mongodb,顾 需要将此用户的到期时间延长. 解决过程: 1)到网站对应tomcat配置里找出等里mongodb的信息(mo ...

  8. 理解使用static import 机制

    J2SE 1.5里引入了“Static Import”机制,借助这一机制,可以用略掉所在的类或接口名的方式,来使用静态成员.本文介绍这一机制的使用方法,以及使用过程中的注意事项. 在Java程序中,是 ...

  9. Scrum Meeting 9

                第九次会议 No_00:工作情况 No_01:任务说明 待完成 已完成 No_10:燃尽图 No_11:照片记录 待更新 No_100:代码/文档签入记录 No_101:出席表 ...

  10. css3-盒模型新增属性

    box-shadow:跟text-shadow类似,可多层叠加 box-shadow:[inset] x y blur [spread] color inset:投影方式,inset内投影,不加参数外 ...