#2510. 「AHOI / HNOI2018」道路

题目描述

W 国的交通呈一棵树的形状。W 国一共有 n−1 个城市和 nnn 个乡村,其中城市从 111 到 n−1 编号,乡村从 111 到 nnn 编号,且 111 号城市是首都。道路都是单向的,本题中我们只考虑从乡村通往首都的道路网络。对于每一个城市,恰有一条公路和一条铁路通向这座城市。对于城市 iii,通向该城市的道路(公路或铁路)的起点,要么是一个乡村,要么是一个编号比 iii 大的城市。没有道路通向任何乡村。除了首都以外,从任何城市或乡村出发只有一条道路;首都没有往 外的道路。从任何乡村出发,沿着唯一往外的道路走,总可以到达首都。

W 国的国王小 W 获得了一笔资金,他决定用这笔资金来改善交通。由于资金有限,小 W 只能翻修 n−1 条道路。小 W 决定对每个城市翻修恰好一条通向它的道路,即从公路和铁路中选择一条并进行翻修。小 W 希望从乡村通向城市可以尽可能地便利,于是根据人口调查的数据,小 W 对每个乡村制定了三个参数,编号为 iii 的乡村的三个参数是 aia_ia​i​​,bib_ib​i​​ 和 cic_ic​i​​。假设从编号为 iii 的乡村走到首都一共需要经过 xxx 条未翻修的公路与 yyy 条未翻修的铁路,那么该乡村的不便利值为

ci⋅(ai+x)⋅(bi+y)c_i \cdot (ai + x) \cdot (bi + y)c​i​​⋅(ai+x)⋅(bi+y)

在给定的翻修方案下,每个乡村的不便利值相加的和为该翻修方案的不便利值。

翻修 n−1 条道路有很多方案,其中不便利值最小的方案称为最优翻修方案,小 W 自然希望找到最优翻修方案,请你帮助他求出这个最优翻修方案的不便利值。

输入格式

第一行为正整数 nnn。 接下来 n−1 行,每行描述一个城市。其中第 iii 行包含两个数 si,tis_i, t_is​i​​,t​i​​。sis_is​i​​ 表示通向第 iii 座城市的公路的起点,tit_it​i​​ 表示通向第 iii 座城市的铁路的起点。如果 si>0s_i > 0s​i​​>0,那么存在一条从第 sis_is​i​​ 座城市通往第 iii 座城市的公路,否则存在一条从第 −si-s_i−s​i​​ 个乡村通往第 iii 座城市的公路;tit_it​i​​ 类似地,如果 ti>0t_i > 0t​i​​>0,那么存在一条从第 tit_it​i​​ 座城市通往第 iii 座城市的铁路,否则存在一条从第 −ti-t_i−t​i​​ 个乡村通往第 iii 座城市的铁路。

接下来 nnn 行,每行描述一个乡村。其中第 iii 行包含三个数 ai,bi,cia_i, b_i, c_ia​i​​,b​i​​,c​i​​,其意义如题面所示。

输出格式

输出一行一个整数,表示最优翻修方案的不便利值。

样例

样例输入 1

6
2 3
4 5
-1 -2
-3 -4
-5 -6
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

样例输出 1

54

样例解释 1

如图所示,我们分别用蓝色、黄色节点表示城市、乡村;用绿色、红色箭头分别表示公路、铁路;用加粗箭头表示翻修的道路。

一种不便利值等于 545454 的方法是:翻修通往城市 222 和城市 555 的铁路,以及通往其他城市的公路。用→\rightarrow→和⇒\Rightarrow⇒表示公路和铁路,用∗→和∗⇒表示翻修的公路和铁路,那么:

  • 编号为 111 的乡村到达首都的路线为:−1∗→3⇒1,经过 000 条未翻修公路和 111 条未翻修铁路,代价为 3×(1+0)×(2+1)=93 \times (1 + 0) \times (2 + 1) = 93×(1+0)×(2+1)=9;
  • 编号为 222 的乡村到达首都的路线为:−2⇒3⇒1,经过 000 条未翻修公路和 222 条未翻修铁路,代价为 2×(1+0)×(3+2)=102 \times (1 + 0) \times (3 + 2) = 102×(1+0)×(3+2)=10;
  • 编号为 333 的乡村到达首都的路线为:−3∗→4→2∗→1,经过 111 条未翻修公路和 000 条未翻修铁路,代价为 3×(2+1)×(1+0)=93 \times (2 + 1) \times (1 + 0) = 93×(2+1)×(1+0)=9;
  • 编号为 444 的乡村到达首都的路线为:−4⇒4→2∗→1,经过 111 条未翻修公路和 111 条未翻修铁路,代价为 1×(2+1)×(3+1)=121 \times (2 + 1) \times (3 + 1) = 121×(2+1)×(3+1)=12;
  • 编号为 555 的乡村到达首都的路线为:−5→5∗⇒2∗→1,经过 111 条未翻修公路和 000 条未翻修铁路,代价为 2×(3+1)×(1+0)=82 \times (3 + 1) \times (1 + 0) = 82×(3+1)×(1+0)=8;
  • 编号为 666 的乡村到达首都的路线为:−6∗⇒5∗⇒2∗→1,经过 000 条未翻修公路和 000 条未翻修铁路,代价为 1×(3+0)×(2+0)=61 \times (3 + 0) \times (2 + 0) = 61×(3+0)×(2+0)=6;

总的不便利值为 9+10+9+12+8+6=549 + 10 + 9 + 12 + 8 + 6 = 549+10+9+12+8+6=54。可以证明这是本数据的最优解。

样例输入 2

9
2 -2
3 -3
4 -4
5 -5
6 -6
7 -7
8 -8
-1 -9
1 60 1
1 60 1
1 60 1
1 60 1
1 60 1
1 60 1
1 60 1
1 60 1
1 60 1

样例输出 2

548

样例解释 2

在这个样例中,显然应该翻修所有公路。

样例输入 3

12
2 4
5 3
-7 10
11 9
-1 6
8 7
-6 -10
-9 -4
-12 -5
-2 -3
-8 -11
53 26 491
24 58 190
17 37 356
15 51 997
30 19 398
3 45 27
52 55 838
16 18 931
58 24 212
43 25 198
54 15 172
34 5 524

样例输出 3

5744902

数据范围与提示

共 202020 组数据,编号为 1∼20。

对于编号 ≤4\le 4≤4 的数据,n≤20n \le 20n≤20;

对于编号为 5∼8 的数据,ai,bi,ci≤5,n≤50;

对于编号为 9∼12 的数据,n≤2000n \le 2000n≤2000;

对于所有的数据,n≤20000n \le 20000n≤20000,1≤ai,bi≤601 \le a_i, b_i \le 601≤a​i​​,b​i​​≤60,1≤ci≤1091 \le c_i \le 10^91≤c​i​​≤10​9​​,si,tis_i, t_is​i​​,t​i​​ 是 [−n,−1]∩(i,n−1] 内的整数,任意乡村可以通过不超过 404040 条道路到达首都。

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 50
using namespace std;
int map[maxn][maxn];
int n,m,head[maxn],num,a[maxn],b[maxn],c[maxn],son[maxn][];
struct node{int to,pre,v,w;}e[maxn*maxn];
void Insert(int from,int to,int w){
e[++num].to=to;
e[num].w=w;
e[num].pre=head[from];
head[from]=num;
}
int cnt[maxn][];
long long ans=;
void dfs(int x,int cnt0,int cnt1){
if(x<=n){
cnt[x][]=cnt0;
cnt[x][]=cnt1;
}
for(int i=head[x];i;i=e[i].pre){
int to=e[i].to;
if(e[i].w==&&e[i].v==)dfs(to,cnt0+,cnt1);
else if(e[i].w==&&e[i].v==)dfs(to,cnt0,cnt1+);
else dfs(to,cnt0,cnt1);
}
}
long long count(int sta){
for(int i=;i<n;i++){
if(sta&(<<(i-))){//连向右孩子的边被重建
e[map[i+n][son[i+n][]]].v=;
e[map[i+n][son[i+n][]]].v=;
}
else {//连向左孩子的边被重建
e[map[i+n][son[i+n][]]].v=;
e[map[i+n][son[i+n][]]].v=;
}
}
dfs(n+,,);
long long res=;
for(int i=;i<=n;i++){
res+=1LL*c[i]*(a[i]+cnt[i][])*(b[i]+cnt[i][]);
}
return res;
}
int main(){
scanf("%d",&n);
m=n+n-;
int x,y;
for(int i=;i<n;i++){
scanf("%d%d",&x,&y);
if(x<)x=-x;
else x+=n;
if(y<)y=-y;
else y+=n;
son[i+n][]=x;son[i+n][]=y;
Insert(i+n,x,);map[i+n][x]=map[x][i+n]=num;
Insert(i+n,y,);map[i+n][y]=map[y][i+n]=num;
}
for(int i=;i<=n;i++)scanf("%d%d%d",&a[i],&b[i],&c[i]);
for(int i=;i<(<<(n-));i++){
ans=min(ans,count(i));
}
cout<<ans<<endl;
return ;
}

20分 暴力

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 20010
using namespace std;
int n,son[maxn][];
long long f[maxn][][];
struct node{long long x,y,z;}a[maxn];
long long dfs(int x,int p,int q){
if(x>=n){
int now=x-n+;
return a[now].z*(a[now].x+p)*(a[now].y+q);
}
if(f[x][p][q]!=f[n+][][])return f[x][p][q];
return f[x][p][q]=min(dfs(son[x][],p,q)+dfs(son[x][],p,q+),dfs(son[x][],p,q)+dfs(son[x][],p+,q));
}
int main(){
int x,y;
scanf("%d",&n);
memset(f,,sizeof(f));
for(int i=;i<n;i++){
scanf("%d%d",&x,&y);
if(x<)x=-x+n-;
if(y<)y=-y+n-;
son[i][]=x;
son[i][]=y;
}
for(int i=;i<=n;i++)
scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].z);
printf("%lld\n",dfs(,,));
return ;
}

100分 树形dp

loj #2510. 「AHOI / HNOI2018」道路的更多相关文章

  1. loj#2510. 「AHOI / HNOI2018」道路 记忆化,dp

    题目链接 https://loj.ac/problem/2510 思路 f[i][a][b]表示到i时,公路个数a,铁路个数b 记忆化 复杂度=状态数=\(nlog^2n\) 代码 #include ...

  2. 【LOJ】#2510. 「AHOI / HNOI2018」道路

    题解 读题是做题关键 我们设\(dp[u][l][r]\)表示\(u\)节点上方没改\(l\)条公路和\(r\)条铁路 然后记忆化搜索,枚举这条点改左边还是右边 代码 #include <bit ...

  3. Loj #2495. 「AHOI / HNOI2018」转盘

    Loj #2495. 「AHOI / HNOI2018」转盘 题目描述 一次小 G 和小 H 原本准备去聚餐,但由于太麻烦了于是题面简化如下: 一个转盘上有摆成一圈的 \(n\) 个物品(编号 \(1 ...

  4. Loj #2494. 「AHOI / HNOI2018」寻宝游戏

    Loj #2494. 「AHOI / HNOI2018」寻宝游戏 题目描述 某大学每年都会有一次 Mystery Hunt 的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得 ...

  5. loj #2509. 「AHOI / HNOI2018」排列

    #2509. 「AHOI / HNOI2018」排列   题目描述 给定 nnn 个整数 a1,a2,…,an(0≤ai≤n),以及 nnn 个整数 w1,w2,…,wn.称 a1,a2,…,an 的 ...

  6. loj #2508. 「AHOI / HNOI2018」游戏

    #2508. 「AHOI / HNOI2018」游戏 题目描述 一次小 G 和小 H 在玩寻宝游戏,有 nnn 个房间排成一列,编号为 1,2,…,n,相邻房间之间都有 111 道门.其中一部分门上有 ...

  7. @loj - 2496@ 「AHOI / HNOI2018」毒瘤

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 从前有一名毒瘤. 毒瘤最近发现了量产毒瘤题的奥秘.考虑如下类型的 ...

  8. loj#2509. 「AHOI / HNOI2018」排列(思维题 set)

    题意 题目链接 Sol 神仙题Orz 首先不难看出如果我们从\(a_i\)向\(i\)连一条边,我们会得到以\(0\)为根的树(因为每个点一定都有一个入度,出现环说明无解),同时在进行排列的时候需要保 ...

  9. loj#2020 「AHOI / HNOI2017」礼物 ntt

    loj#2020 「AHOI / HNOI2017」礼物 链接 bzoj没\(letex\),差评 loj luogu 思路 最小化\(\sum\limits_1^n(a_i-b_i)^2\) 设改变 ...

随机推荐

  1. ffmpeg函数介绍

    本文对在使用ffmpeg进行音视频编解码时使用到的一些函数做一个简单介绍,我当前使用的ffmpeg版本为:0.8.5,因为本人发现在不同的版本中,有些函数名称会有点小改动,所以在此有必要说明下ffmp ...

  2. Python基础学习五 内置模块

    time 模块 1 >>> import time 2 >>> time.time() 3 1491064723.808669 4 >>> # t ...

  3. 【284】◀▶ arcpy.da & arcpy 数据访问模块

    使用游标访问数据 数据访问模块 (arcpy.da) 参考: ArcGIS Python编程案例(9)-ArcPy数据访问模块 读取几何 写入几何 使用 Python 指定查询 01   da.Sea ...

  4. Java虚拟机(三):垃圾收集器

    一.串行(Serial)收集器 最古老,最稳定 效率高 可能会产生较长的停顿 -XX:+UseSerialGC 新生代.老年代使用串行回收 新生代复制算法 老年代标记-压缩 二.并行收集器 1. Pa ...

  5. zookeeper伪集群的搭建

    由于公司服务器数量的限制,我们往往没有那么多的服务器用来搭建zookeeper的集群,所以产生了伪集群的搭建,也就是将多个zookeeper搭建在同一台机器上. 准备工作: 1,一台服务器,我们这里用 ...

  6. 面试中的C++常见问题

    1.在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”? 答:首先,extern是C/C++语言中表明函数和全局变量作用范围的关键字,该关键字告诉编译器,其声明的函数和变量可 ...

  7. Druid配置属性列表及含义

    前两天,在排查springBoot使用双数据源出现的运行一段时候出现了数据库连接断开的问题的时候,查了很多关于Druid数据库连接池配置的文章,虽然最后问题的原因不是属性配置的问题,也可以说是 属性配 ...

  8. 面试题: java多线程 背1

    如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其 ...

  9. Luogu 3261 [JLOI2015]城池攻占

    BZOJ 4003 需要实现一个可并堆. 每个点维护一个小根堆,然后一开始把所有骑士加入到它所在的点的小根堆当中,实际上空间是$O(m)$的,然后我们从上到下不断合并这个小根堆,合并完之后如果遇到堆顶 ...

  10. Vue.js 安装及其环境搭建

    For me or other first studying vue.js. For Windows PC: 1.先安装node.js 安装官网最新的即可 版本应该要大于6.0版本 nodejs的官网 ...