题解 P1453 【城市环路】
感觉基环树(or环套树)的题目一般都是找到树上的环,断掉一条边再进行树上的操作(如noip2018P5022 旅行)
双倍经验:P2607 [ZJOI2008]骑士
P1453和P2607这两题实际上就是基环树上的P1352 没有上司的舞会,用树形DP即可,但是因为有环,所以要先找到环再删一条边才能DP
至于树形DP就不多说了,毕竟是基环树,最主要的就是找环操作了,翻了翻题解,大概有下面几种方法:
一. 读入时判断
并查集 ,若两点在一个并查集中则记录下来,不连边不合并
(不建议使用)bool记录点是否出现过,若读入时两点在之前都已出现了,则为环,不连边(BUG:本题数据较弱可过,但可能在一些数据中出错,看评论中有一组hack数据:5 1 2 3 4 5 0 1 2 3 2 4 0 2 3 4 9.0,答案为63.0,但这种找环方法会超时)
二、读入后判断
如本程序,dfs找环,找到时记录两点a,b或边编号e,dp时不仅要判断v!=fa,还应判断(u!=a || v!=b) && (u!=b || v!=a)或(e!=i && (e^1)!=i)(双向边)
(不建议使用)连单向边u->v(注意要保证有有向环),记录fa[v]=u,从一个已存在的点开始不断找fa直到遇到走过的则找到了环。这种写法可以用在P2607(见这个题解),此题未必可行
while(!vis[fa[rt]]) rt=fa[rt],vis[rt]=1;//rt与fa[rt]连为了环
对于此题,找到环上两点a,b后,分别以a,b为根做两次树形DP,第一次取f[a][0],第二次取f[b][0](这样保证a与b虽相邻但不会同时被被取),取max(f[a][0],f[b][0])与K相乘即可
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define ll int //这个代码是在P2607的基础上修改的,所以直接把ll定义为int了
const int N=1e5+100;
int h[N],rt,rt2,n,cnt,val[N];
bool vis[N];
ll f[N][2],ans;
struct edge {
int v,h;
} e[N<<1];
inline void add(int u,int v) {
e[++cnt]=(edge) {
v,h[u]
},h[u]=cnt;
}
void dp(int x,int fa) {
vis[x]=1,f[x][1]=val[x];
for (int i=h[x],v; i; i=e[i].h) {
v=e[i].v;
if ((x!=rt || v!=rt2) && (x!=rt2 || v!=rt) && v!=fa)
dp(v,x),
f[x][0]+=max(f[v][0],f[v][1]),
f[x][1]+=f[v][0];
}
}
bool find(int x,int fa) { //dfs找环
vis[x]=1;
for(int i=h[x]; i; i=e[i].h)
if (e[i].v^fa)
if (vis[e[i].v]) {
rt=e[i].v,rt2=x; //找到了环,记录起端点(相当于切断i这条边)
return 1;
} else if (find(e[i].v,x)) return 1;
}
void solve(int x) { //分别以两端点做树形DP
find(x,-1);
dp(rt,rt);
ll tmp=f[rt][0];
memset(f,0,sizeof f);
dp(rt2,rt2);
ans=max(tmp,f[rt2][0]);
}
int main() {
scanf("%d",&n);
for (int i=0; i<n; i++) scanf("%d",&val[i]);
for (int i=1,x,y; i<=n; i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
solve(0); //注意若是森林需枚举1~n的点
double tmp;
scanf("%lf",&tmp);
printf("%.1lf",(double)ans*tmp);
}
题解 P1453 【城市环路】的更多相关文章
- BSOJ3760||洛谷P1453 城市环路 题解
城市环路 Description 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域——城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环 ...
- 洛谷 P1453 城市环路 ( 基环树树形dp )
题目链接 题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域--城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市 ...
- P1453 城市环路
题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域——城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市中心. 题 ...
- luogu P1453 城市环路
题目描述 整个城市可以看做一个N个点,N条边的单圈图(保证图连通),唯一的环便是绕城的环路.保证环上任意两点有且只有2条路径互通.图中的其它部分皆隶属城市郊区. 现在,有一位名叫Jim的同学想在B市开 ...
- LUOGU P1453 城市环路(基环树+dp)
传送门 解题思路 一道基环树上$dp$的题,这种题比较套路吧,首先第一遍$dfs$把环找出来,然后对于环上的每一个点都向它子树内做一次树形$dp$,$f[i][0/1]$表示到了$i$这个点选或不选的 ...
- [ZJOI2008]骑士 题解
题面 这道题稍微想一想就会联想到树形DP的入门题:没有上司的舞会: 但是再想一想会发现这根本就不是一颗树,因为它比树多了一条边: 这时候我们引入一个新的概念:基环树: 顾名思义(??),基环树就是在一 ...
- 2021record
2021-10-14 P2577 [ZJOI2004]午餐 2021-10-13 CF815C Karen and Supermarket(小小紫题,可笑可笑) P6748 『MdOI R3』Fall ...
- 2018 AI产业界大盘点
2018 AI产业界大盘点 大事件盘点 “ 1.24——Facebook人工智能部门负责人Yann LeCun宣布卸任 Facebook人工智能研究部门(FAIR)的负责人Yann LeCun宣布卸 ...
- 绍一集训Round#1
到了之后看题,T1一看发现真熟悉,和之前做的一道题真的像,然后内心: 这里是绍一啊,不可能就出这么简单的题 我题意没理解错啊,这不是单独计算每条边的贡献么 维护一个人数的大小,然后直接搞一波就可以了吧 ...
随机推荐
- Centos7 修改/etc/profile错误后导致所有命令“not found”
因为Centos7中运行着两个版本的php,今天在设置环境变量时导致所有命令都 "not found". 修复方式: 第一:执行 /bin/vi /etc/profile 把文件修 ...
- ubuntu设置ulimit
centos系统的设置ulimit的时候是直接修改/etc/security/limits.conf文件,但是在ubuntu中却不行, ubuntu先修改/etc/security/limits.co ...
- php中的require和include区别
require是无条件包含也就是如果一个流程里加入require,无论条件成立与否都会先执行require 1.require 的使用方法如 require("MyRequireFile.p ...
- 实用沙盒工具 —— VMware Workstation15安装教程
一:简介 VMware Workstation(中文名"威睿工作站")是一款功能强大的桌面虚拟计算机软件,提供用户可在单一的桌面上同时运行不同的操作系统,和进行开发.测试 .部署新 ...
- MPI Maelstrom POJ - 1502 floyd
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> usin ...
- #助力CSP2019# OI中容易出现的**错误汇总
多测不清空,爆0两行泪 3年OI一场空,不开long long见祖宗 线段树空间需要开4倍 读入有负数的时候,如果要写快读,要识别负号 持续更新
- MySQL安装版安装过程
步骤1 步骤2 步骤3 步骤4 步骤5 步骤6 步骤7 步骤8 步骤9 步骤10 步骤11 步骤12
- Linux下搭建PHP环境的参考文章小记
之前也在Linux上安装过两次,但是当我再次需要安装时,还是很多不懂的地方,于是记下此篇,以防下次再费经心思找到不合适的文章,瞎折腾. 通过参考这几篇文章,成功的安装好了自己的PHP(LNMP)环境. ...
- 关于Git的右键菜单消失的处理
右键菜单 Git Bash Here window + R,输入regedit回车进入注册表 进入如下目录 HKEY_CLASSES_ROOT\Directory\Background\shell 在 ...
- MySQL启动和停止
MySQL视为大仓库,关闭的时候有权限有身份都无法进入使用的时候要保持启用状态 方式一: 计算机游击找到“管理”打开 左侧栏目中找到“服务和应用程序”打开 打开服务 找到MySQL...,右击.... ...