[SCOI2008]城堡

最大值最小,显然二分答案,但考虑二分后如何 check

\(n\) 个点 \(n\) 条边,显然这是一个基环树森林。对于基环树,常用的套路是拆环为链,枚举删去哪条边。但这题是基环树森林,拆环为链的复杂太高,考虑将环和树分开处理。

树上是一个很典型的 dp,和将军令一样(不了解的可以观看我的相关博客),注意处理下原来关键点的影响即可。

环上的部分要分成两种情况:

  • 第一种是环上没有关键点。需要先处理该点是否被其它点子树内的关键点覆盖。令 \(len\) 表示处理完子树内的点后还可以影响环上多少长度,若 \(len\times 2>\) 环的长度,则整个环只需要新添一个点就可以全部被覆盖。否则会变成一个经典贪心问题,在环上有一些区间,每个区间表示表示关键点被放置在该区间时,某个点才会被覆盖,求最少要有多少区间才能覆盖这个环。
  • 环上有关键点,其实也差不多,只是最后求最少区间覆盖环时有了一个起点。
点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int N=200,inf=1e9;
int n,m,K,d[N][N],v[N],w[N],flag[N],vis[N],f[N],g[N];
int idx,Time;
vector<pii>e[N];
stack<int>stk;
struct node{
int l,r;
};
struct tree{
int circle[N],cnt,rank[N],pos,dis[N],s[N],in_cir[N],sum,k,tot,R[N],nxt[N];
node seg[N];
void ins(int x){
circle[++cnt]=x;
rank[x]=cnt;
in_cir[x]=1;
}
void work(){
for(int i=1;i<=cnt;i++){
if(flag[circle[i]]){
pos=i;
break;
}
}
for(int i=1;i<=cnt;i++){
dis[i]=dis[i+cnt]=d[circle[i]][circle[i%cnt+1]];
}
for(int i=1;i<=cnt*2;i++){
s[i+1]=s[i]+dis[i];
}
}
void dfs(int u,int fa){
f[u]=0;
g[u]=inf;
for(auto x:e[u]){
int v=x.first,w=x.second;
if(in_cir[v]||v==fa){
continue;
}
dfs(v,u);
f[u]=max(f[u],f[v]+w);
g[u]=min(g[u],g[v]+w);
}
if(flag[u]){
g[u]=0;
}
if(f[u]+g[u]<=k){
f[u]=-inf;
}
if(f[u]+d[u][fa]>k){
f[u]=-inf;
g[u]=0;
sum++;
}
}
int solve(){
// cerr<<k<<endl;
tot=sum=0;
for(int i=1;i<=cnt;i++){
dfs(circle[i],0);
}
int fl=0;
for(int i=1;i<=cnt*2;i++){
R[i]=inf;
}
for(int i=1;i<=cnt;i++){
bool flg=0;
for(int j=1;j<=cnt;j++){
int Dis=abs(s[i]-s[j]);
Dis=min(Dis,s[cnt+1]-Dis);
if(f[circle[i]]+g[circle[j]]+Dis<=k){
flg=1;
break;
}
}
if(flg){
continue;
}
int len=k-f[circle[i]];
if(len*2>=s[cnt+1]){
if(!pos){
fl=1;
}
continue;
}
++tot;
if(s[i]+dis[cnt]>len){
seg[tot].l=1,seg[tot].r=2*cnt;
for(int j=i;j;j--){
if(s[i]-s[j]>len){
seg[tot].l=j+1;
break;
}
}
for(int j=i+1;j<=cnt*2;j++){
if(s[j]-s[i]>len){
seg[tot].r=j-1;
break;
}
}
seg[tot+1].l=seg[tot].l+cnt;
seg[tot+1].r=seg[tot].r+cnt;
++tot;
}
else{
seg[tot].l=1,seg[tot].r=2*cnt;
for(int j=i+cnt;j;j--){
if(s[i+cnt]-s[j]>len){
seg[tot].l=j+1;
break;
}
}
for(int j=i+cnt;j<=2*cnt;j++){
if(s[j]-s[i+cnt]>len){
seg[tot].r=j-1;
break;
}
}
}
}
// cerr<<tot<<' '<<fl<<endl;
if(!tot){
return sum+fl;
}
for(int i=1;i<=tot;i++){
R[seg[i].l]=min(R[seg[i].l],seg[i].r);
}
int c=0,mn=inf;
for(int i=2*cnt;i;i--){
nxt[i]=mn;
mn=min(mn,R[i]);
}
if(pos){
int x=pos;
while(nxt[x]<pos+cnt){
c++;
x=nxt[x];
}
}
else{
c=inf;
for(int i=1;i<=cnt;i++){
int x=i,S=1;
while(nxt[x]<i+cnt){
S++;
x=nxt[x];
}
c=min(c,S);
}
}
c=max(c,fl);
return sum+c;
}
}tr[N];
void visit(int u,int fa){
vis[u]=Time;
for(auto x:e[u]){
int v=x.first;
if(vis[v]==Time){
continue;
}
visit(v,u);
}
}
bool dfs(int u,int fa){
stk.push(u);
vis[u]=Time;
bool First=1;
for(auto x:e[u]){
int v=x.first;
if(vis[v]==Time){
if(v==fa){
if(First){
First=0;
continue;
}
}
while(stk.top()!=v){
tr[idx].ins(stk.top());
stk.pop();
}
tr[idx].ins(stk.top());
stk.pop();
return 1;
}
if(dfs(v,u)){
return 1;
}
}
stk.pop();
return 0;
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
read(n),read(m),read(K);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
d[i][j]=inf;
}
}
for(int i=1;i<=n;i++){
read(v[i]);
v[i]++;
}
for(int i=1;i<=n;i++){
read(w[i]);
e[i].pb(mp(v[i],w[i]));
e[v[i]].pb(mp(i,w[i]));
d[i][v[i]]=d[v[i]][i]=min(d[i][v[i]],w[i]);
}
for(int i=1;i<=m;i++){
int x;
read(x);
flag[x+1]=1;
}
for(int i=1;i<=n;i++){
if(!vis[i]){
Time++;
idx++;
visit(i,0);
Time++;
dfs(i,0);
tr[idx].work();
}
}
int l=0,r=inf,ans=inf;
while(l<=r){
int mid=(l+r)>>1,x=0;
// cerr<<mid<<' ';
for(int i=1;i<=idx;i++){
tr[i].k=mid;
x+=tr[i].solve();
}
if(x>K){
l=mid+1;
}
else{
r=mid-1;
ans=mid;
}
}
write_endl(ans);
return 0;
}

[[SCOI2008]城堡] 解题报告的更多相关文章

  1. 夏令营提高班上午上机测试 Day 4 解题报告

    我要是没记错的话,今天的题难度算挺适中的. *标程来自高天宇哥哥 T1:小G的字符串 题目描述 有一天,小 L 给小 G 出了这样一道题:生成一个长度为 n 的.全由小写英文字母构成的字符串,只能使用 ...

  2. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

  3. 二模13day1解题报告

    二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...

  4. BZOJ 1051 最受欢迎的牛 解题报告

    题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4438  Solved: 2353[S ...

  5. 习题:codevs 2822 爱在心中 解题报告

    这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...

  6. 习题:codevs 1035 火车停留解题报告

    本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...

  7. 习题: codevs 2492 上帝造题的七分钟2 解题报告

    这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...

  8. 习题:codevs 1519 过路费 解题报告

    今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...

  9. NOIP2016提高组解题报告

    NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合

  10. LeetCode 解题报告索引

    最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中......                        ...

随机推荐

  1. Angular架构学习

    定义 Angular 是一个用 HTML 和 JavaScript 或者一个可以编译成 JavaScript 的语言(例如 Dart 或者 TypeScript ),来构建客户端应用的框架. 写 An ...

  2. Python之常用数据类型详解

    tuple 元组 1 # 定义 2 temp = (2, ) # 规范定义,单个元素的元组 3 tem = 2, # 可行,但不规范定义 4 tep = () # 空元组 5 6 tp = (1, ' ...

  3. 01.html大致主体格式

    <!DOCTYPE html> 不是HTML标签,就是文档声明标签 告诉浏览器使用哪种html版本来显示网页,其必须在文档中的最前面位置,要放在<html>标签之前, < ...

  4. 如何加快打开网页的速度------通过调节“QoS数据包计划程序”的“限制可保留宽带”实现&如何解决win10可能找不到gpedit.msc的问题

    参考:http://www.windowszj.com/news/win10/42119.html http://www.docin.com/p-1510367352.html(QoS数据包计划程序有 ...

  5. RPA的价值和优势

    RPA机器人流程自动化(Robotic process automation):能够代替或者协助人类在计算机.RPA手机等数字化设备中完成重复性工作与任务. 只要预先设计好使用规则,RPA就可以模拟人 ...

  6. 关于js通过修改行内样式来修改元素样式

    关于js通过修改行内样式来修改元素样式 1.当我们通过使用js来修改html元素的样式时,使用的方法是为元素添加行内样式, 此时的js样式是生效的,因为行内样式优先级高于类名 2.如果已有同属性的行内 ...

  7. Python 爬虫入门(一)环境搭建

    一.梳理图 Python是个啥.为啥学习.作用域,随便查一下什么信息都有 本人目前是Java开发,在学习爬虫时发现在爬虫方面,Python比Java简单.方便.实用很多,不是不能做,只是单纯的适合 在 ...

  8. TCP 三次握手,给我长脸了噢

    大家好,我是小富~ 个人资源分享网站:FIRE 本文收录在 Springboot-Notebook 面试锦集 前言 之前有个小伙伴在技术交流群里咨询过一个问题,我当时还给提供了点排查思路,是个典型的八 ...

  9. 机器学习(二):感知机+svm习题 感知机手工推导参数更新 svm手推求解二维坐标超平面直线方程

    作业1: 输入: 训练数据集 \(T = {(x1; y1); (x2; y2),..., (xN; yN)}\) 其中,\(x \in R^n\), \(y \in Y = \{+1, -1\}\) ...

  10. Nmap学习

    Nmap学习 一.主机发现 1.全面扫描/综合扫描 nmap -A 192.168.142.201 2.Ping扫描 nmap -sP 192.168.142.0/24 3.免Ping扫描,穿透防火墙 ...