考前随便做点水题愉♂悦身心 有助于退役

这题意思其实就是说要把外向基环树森林改成一个环的最小代价。

依照套路,先对每棵基环树的树做dp,这里因为要是环,要把所有的树都拆成链,然后连接。所以考虑以最小代价拆掉每一个树。

因为对于树的每层,只能选择出一个儿子作为链的部分保留下来,所以贪心的尽量选权值大的儿子留下来,其他的全部作为另一条链的开头准备接到环上。

所以树的部分就是一个简单的树形DP。

然后看环上的DP,相当于是要把我们之前搞出来的所有的链全部接上去,所以环上至少要有一个边断开,让这些链接上去。

所以环上,每条边要么把入点连着的链断开,接入环中某处,要么直接断掉这条边将一些链给接上去。

这时只要对环上每条边以这两种方案择优选取,最后发现最优方案如果没有环上边被断开,就强制找一个最小的代价让环上边断掉。

当图是一个基环树森林的时候,不影响正确性,我们需要让每棵树的环都断开一个,以互相接入成为环,所以每个基环树可以独立做。

不过注意一个特例:整个图就是一个环,这时就不需要断了。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define mst(x) memset(x,0,sizeof x)
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=1e5+,INF=0x3f3f3f3f;
struct thxorz{
int head[N],nxt[N<<],to[N<<],tot;
thxorz(){tot=;}
inline void add(int x,int y){
to[++tot]=y,nxt[tot]=head[x],head[x]=tot;
to[++tot]=x,nxt[tot]=head[y],head[y]=tot;
}
}G;
ll ans;
int n;
#define y G.to[j]
int vis[N],lp[N],val[N],chain[N],m,lpfa,flag,rt;
void dfs(int x){//dbg(x);
vis[x]=;
for(register int j=G.head[x];j&&!flag;j=G.nxt[j])if(j&){//mistake:the direction of the edge!
if(vis[y])return lpfa=y,flag=,lp[m=]=x,void();
else{dfs(y);if(flag)lp[++m]=x;}
}
if(!flag)vis[x]=;
if(x==lpfa)flag=;
}
void dp(int x){//dbg(x);
vis[x]=;ll sum=;
for(register int j=G.head[x];j;j=G.nxt[j])if(!vis[y])dp(y),sum+=val[y],MAX(chain[x],val[y]);
ans+=sum-chain[x];
}
#undef y
int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(n);
for(register int i=,x;i<=n;++i)read(x),read(val[i]),G.add(x,i);
for(register int i=;i<=n;++i)if(!vis[i]){//dbg(i);
flag=,dfs(i);int chosen=;//dbg("ok");dbg(m);
if(m==n)break;
for(register int j=;j<=m;++j)dp(lp[j]);//dbg(lp[j]);
#define nxt (j+1>m?1:j+1)//attention to the order..
for(register int j=;j<=m;++j){
if(chain[lp[j]]<val[lp[nxt]])ans+=chain[lp[j]];
else ans+=val[lp[nxt]],chosen=;
}
if(!chosen){//dbg2(i,chosen);
int tmp=INF;
for(register int j=;j<=m;++j)MIN(tmp,-chain[lp[j]]+val[lp[nxt]]);
ans+=tmp;
}
}
printf("%lld\n",ans);
return ;
}

总结:这题也涉及一个断环的操作,不过是需要考察性质之后发现的,是一个不那么显然的题目。。。

luogu3651 展翅翱翔之时 (はばたきのとき)[基环树+贪心]的更多相关文章

  1. 洛谷P3656 展翅翱翔之时 (はばたきのとき)(洛谷2017.3月赛round1 t4)

    题目背景 船が往くよミライへ旅立とう 船只启航 朝未来展开旅途 青い空笑ってる(なにがしたい?) 湛蓝天空露出微笑(想做些什么?) ヒカリになろうミライを照らしたい 化作光芒吧 想就此照亮未来 輝きは ...

  2. 【洛谷P3651】展翅翱翔之时

    难以吐槽出题人的中二病…… 这题有点类似ZJOI2008 骑士,先跑树上的,最后拆环即可. #include<bits/stdc++.h> #define N 100005 typedef ...

  3. tyvj1940创世纪——贪心(基环树)

    题目:http://www.joyoi.cn/problem/tyvj-1940 基环树的样子,看了书上的讲解,准备写树上DP,然后挂了: #include<iostream> #incl ...

  4. 与图论的邂逅01:树的直径&基环树&单调队列

    树的直径 定义:树中最远的两个节点之间的距离被称为树的直径.  怎么求呢?有两种官方的算法(不要问官方指谁我也不晓得): 1.两次搜索.首先任选一个点,从它开始搜索,找到离它最远的节点x.然后从x开始 ...

  5. COCI2014/2015 Contest#1 D MAFIJA【基环树最大独立点集】

    T1725 天黑请闭眼 Online Judge:COCI2014/2015 Contest#1 D MAFIJA(原题) Label:基环树,断环+树形Dp,贪心+拓扑 题目描述 最近天黑请闭眼在 ...

  6. 【BZOJ1791】【IOI2008】【基环树】island(status第一速度)

      1791: [Ioi2008]Island 岛屿  Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 908  Solved: 159 [Su ...

  7. BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心

    BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...

  8. 『Island 基环树直径』

    Island(IOI 2008) Description 你准备浏览一个公园,该公园由 N 个岛屿组成,当地管理部门从每个岛屿 i 出发向另外一个岛屿建了一座长度为 L_i 的桥,不过桥是可以双向行走 ...

  9. [Codeforces235D]Graph Game——概率与期望+基环树+容斥

    题目链接: Codeforces235D 题目大意:给出一棵基环树,并给出如下点分治过程,求点数总遍历次数的期望. 点分治过程: 1.遍历当前联通块内所有点 2.随机选择联通块内一个点删除掉 3.对新 ...

随机推荐

  1. Linux ps 查看进程

    [root@wang /]# ps aux ps -elf ^C [root@wang /]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIM ...

  2. 数据结构——关于任一二叉树n0=n2+1的证明

    对于任一二叉树,若度为2的结点有n2个,则叶子结点数必为n2+1 证明: 假设该二叉树总共有n个结点(n=n0+n1+n2),则该二叉树总共会有n-1条边,度为2的结点会延伸出两条边, 同理,度为1的 ...

  3. 【转帖】Samba AD DC(域控制器)的配置

    Samba AD DC(域控制器)的配置 http://lihaitao.cn/?p=299 山东前辈写的blog 挺好的.. 改天做实验. 发表于2017年3月7日由李海涛 ■Samba AD DC ...

  4. Hadoop和Spark的Shuffer过程对比解析

    Hadoop Shuffer Hadoop 的shuffer主要分为两个阶段:Map.Reduce. Map-Shuffer: 这个阶段发生在map阶段之后,数据写入内存之前,在数据写入内存的过程就已 ...

  5. 使用pycharm开发web——django2.1.5(三)创建models并进入交互界面shell做一些简单操作

    这里model可以认为是数据对象本身 相当于在写java代码时候model目录下创建的实体类,models.py 中可以包含多个实体类,感觉这个操作挺骚的 下面是polls app里面的models, ...

  6. mybatis缓存机制与装饰者模式

    mybatis 缓存 MyBatis的二级缓存的设计原理 装饰者模式

  7. RocketMQ源码学习--消息存储篇

    转载. https://blog.csdn.net/mr253727942/article/details/55805876 1.序言 今天来和大家探讨一下RocketMQ在消息存储方面所作出的努力, ...

  8. 【Python基础】07_Python中的模块

    1.模块的概念 模块 就好比 工具包,要想使用这个工具包中的工具,就需要 导入import 这个模块 每一个以扩展名 .py 结尾的 Python源代码文件 都是一个 模块 在模块中定义的 全局变量. ...

  9. MySQL 聚合函数(一)聚合(组合)函数概述

    MySQL版本:5.7+ 本节介绍对值的集合进行操作的组合(聚合)函数.翻译自:Aggregate (GROUP BY) Function Descriptions 一.MySQL 5.7中的聚合函数 ...

  10. 《深入理解 Java 虚拟机》学习 -- 类加载机制

    <深入理解 Java 虚拟机>学习 -- 类加载机制 1. 概述 虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的 J ...