题目描述

整个城市可以看做一个N个点,N条边的单圈图(保证图连通),唯一的环便是绕城的环路。保证环上任意两点有且只有2条路径互通。图中的其它部分皆隶属城市郊区。

现在,有一位名叫Jim的同学想在B市开店,但是任意一条边的2个点不能同时开店,每个点都有一定的人流量Pi,在该点开店的利润就等于该店的人流量Pi×K(K≤10000),K的值将给出。

Jim想尽量多的赚取利润,请问他应该在哪些地方开店?

输入格式

第一行一个整数N 代表城市中点的个数。城市中的N个点由0~N-1编号。

第二行N个正整数,表示每个点的人流量Pi(Pi≤10000)。

下面N行,每行2个整数A,B,表示A,B建有一条双向路。

最后一行一个实数K。

输出格式

一个实数M,(保留1位小数),代表开店的最大利润。


很明显是基环树的题。

首先最后的K是没有什么用的,因为我们的运算里只有加法,所以把K放到最后乘也不影响。我们先不把K算进去。

先考虑一棵树的情况。设dp(u,0/1)表示u的子树可以得到的最大利润,并且u是选(1)还是不选(0)。那么递推公式显然:

\[dp[u][1]=\sum_{v{\in}son[u]} dp[v][0];\\
dp[u][0]=\sum_{v{\in}son[u]} Max(dp[v][0],dp[v][1]);
\]

初始化dp(u,0)=0,dp(u,1)=P(u)。目标状态为Max(dp(root,0/1))。

然而基环树就不那么简单。

朴素的做法就是枚举环上的每条边,把它断掉之后原图会变成一棵树,然后在树上做刚才的dp,得出对应的ans。枚举完所有边后去最大值即可。

但是我们发现断开一条边以后对于每个点选与不选没有影响。但是可以消除后效性。所以我们只需要断开任意一条边,然后分别以这条边的两个端点为根dp一遍即可。

时间复杂度为O(N)。

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 1000001
#define inf 0x3f3f3f3f
using namespace std; struct edge{
int to,next;
edge(){}
edge(const int &_to,const int &_next){ to=_to,next=_next; }
}e[maxn<<1];
int head[maxn],k;
int n,val[maxn],ans;
double K; inline int read(){
register int x(0),f(1); register char c(getchar());
while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
inline void add(const int &u,const int &v){ e[k]=edge(v,head[u]),head[u]=k++; } bool flag[maxn];
int s,t;
inline void getloop(){
for(register int i=0;i<k;i+=2){
int u=e[i].to,v=e[i^1].to;
if(flag[u]&&flag[v]){ s=u,t=v; return; }
flag[u]=flag[v]=true;
}
} int dp[maxn][2];
bool vis[maxn];
void dfs(int u){
vis[u]=true,dp[u][1]=val[u],dp[u][0]=0;
for(register int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(vis[v]) continue;
dfs(v),dp[u][0]+=max(dp[v][0],dp[v][1]),dp[u][1]+=dp[v][0];
}
} int main(){
memset(head,-1,sizeof head);
n=read();
for(register int i=1;i<=n;i++) val[i]=read();
for(register int i=1;i<=n;i++){
int u=read()+1,v=read()+1;
add(u,v),add(v,u);
}
scanf("%lf",&K); getloop();
dfs(s),ans=max(ans,dp[s][0]);
memset(vis,false,sizeof vis);
dfs(t),ans=max(ans,dp[t][0]);
printf("%.1lf\n",ans*K);
return 0;
}

luogu P1453 城市环路的更多相关文章

  1. LUOGU P1453 城市环路(基环树+dp)

    传送门 解题思路 一道基环树上$dp$的题,这种题比较套路吧,首先第一遍$dfs$把环找出来,然后对于环上的每一个点都向它子树内做一次树形$dp$,$f[i][0/1]$表示到了$i$这个点选或不选的 ...

  2. BSOJ3760||洛谷P1453 城市环路 题解

    城市环路 Description 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域——城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环 ...

  3. 洛谷 P1453 城市环路 ( 基环树树形dp )

    题目链接 题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域--城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市 ...

  4. P1453 城市环路

    题目背景 一座城市,往往会被人们划分为几个区域,例如住宅区.商业区.工业区等等.B市就被分为了以下的两个区域——城市中心和城市郊区.在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市中心. 题 ...

  5. 题解 P1453 【城市环路】

    P1453 城市环路 感觉基环树(or环套树)的题目一般都是找到树上的环,断掉一条边再进行树上的操作(如noip2018P5022 旅行) 双倍经验:P2607 [ZJOI2008]骑士 P1453和 ...

  6. luogu P1401 城市

    题目链接 luogu P1401 城市 题解 二分最小边权,dinic检验 代码 // luogu-judger-enable-o2 /* 二分最小边权,dinic检验 */ #include< ...

  7. luogu P4842 城市旅行

    嘟嘟嘟 好题,好题 刚开始突发奇想写了一个\(O(n ^ 2)\)暴力,结果竟然过了?!后来才知道是上传题的人把单个数据点开成了10s-- 不过不得不说我这暴力写的挺好看的.删边模仿链表删边,加边的时 ...

  8. Luogu P1401 城市(二分+网络流)

    P1401 城市 题意 题目描述 N(2<=n<=200)个城市,M(1<=m<=40000)条无向边,你要找T(1<=T<=200)条从城市1到城市N的路,使得最 ...

  9. [ZJOI2008]骑士 题解

    题面 这道题稍微想一想就会联想到树形DP的入门题:没有上司的舞会: 但是再想一想会发现这根本就不是一颗树,因为它比树多了一条边: 这时候我们引入一个新的概念:基环树: 顾名思义(??),基环树就是在一 ...

随机推荐

  1. 02-flask-路由基础

    代码 from flask import Flask # 创建Flask对象 app = Flask(__name__) # 定义路由 @app.route('/') def index(): # 函 ...

  2. 精尽Spring MVC源码分析 - HandlerAdapter 组件(二)之 ServletInvocableHandlerMethod

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  3. 持久层之 MyBatis: 第二篇 :动态SQL And多表查询

    MyBatis入门到精通 完整CRUD UserDaoImpl 编写UserDao对应的UserDaoMapper.xml 添加UserDao的测试用例 编写UserDao的测试用例 解决数据库字段名 ...

  4. K-NN(最近邻分类算法 python

    # algorithm:K-NN(最近邻分类算法)# author:Kermit.L# time: 2016-8-7 #======================================== ...

  5. linux操作系统及常用命令

    GUN:GUN is Not UnixGPL:General Public License.通用公共许可证,版权 Copyright,Copyleft 开源协议LGPL:lesserGPLv2GPLv ...

  6. Docker部署tomcat+nginx+mysql,创建一个tomcat集群

    Docker的部署可以选择虚拟机或者云服务器,我自己选择的是本机安装centos7虚拟机: 1.虚拟机安装登录成功后开始部署docker: 首先了解docker是一个开源应用容器引擎,基于Go语言遵循 ...

  7. Redis入门指导

    前言 本文提供全网最完整的Redis入门指导教程,下面我们从下载Redis安装包开始,一步一步的学习使用. 下载Redis 官网提供的Redis安装包是服务于Linux的,而我们需要在Window下使 ...

  8. [从源码学设计]蚂蚁金服SOFARegistry之Data节点变更

    [从源码学设计]蚂蚁金服SOFARegistry之Data节点变更 目录 [从源码学设计]蚂蚁金服SOFARegistry之Data节点变更 0x00 摘要 0x02 引子 0x03 业务范畴 3.1 ...

  9. ReentrantLock锁-CAS与阻塞

    ReentrantLock锁 ReentrantLock通过原子操作和阻塞实现锁原理,一般使用lock获取锁,unlock释放锁 lock的时候可能被其他线程获得所,那么此线程会阻塞自己,关键原理底层 ...

  10. Loki 初体验

    Loki 是什么 Loki 是 Grafana Lab开发的一套日志系统,使用Go语言实现.根据官方的介绍, Loki,高可用性,多租户的日志聚合系统,受到Prometheus的启发.它的设计非常经济 ...