博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 5289: [Hnoi2018]排列
阅读量:4614 次
发布时间:2019-06-09

本文共 1946 字,大约阅读时间需要 6 分钟。

Description

1146405-20180418083512178-1794462806.png

Solution

首先注意到实际上约束关系构成了一棵树

考虑这个排列 \(p\),编号为 \(a[i]\) 的出现了,\(i\) 才可以出现
那么如果连边 \((a[i],i)\),就会构成一棵以 \(0\) 为根的树,每一个点只有一个父亲
否则就不合法

因为要父亲被选入,这个点才能被选入,所以排列 \(p\),相当于是这棵树的一种合法的拓扑序

要求的就是代价最大的一个拓扑序
那么问题就和 \(POJ\,2054\) 一样的做法了,用一个神奇的贪心

每次找出全局的权值最小值,往父亲合并,合并成新节点,权值为平均值,即 \(\frac{\sum w_i}{size}\)

答案加上被合并的点的权值乘以父亲的 \(size\)
正确性感性理解一下,具体证明和国王游戏差不多,发现 \(swap\) 之后不会更优
实现可以用一个堆或者 \(set\) 实现
然而 \(set\) 被卡常了,开 \(O2\) 才能过

#include
using namespace std;typedef long long ll;const int N=1000010;int n,a[N],w[N],head[N],nxt[N],to[N],num=0,in[N],fa[N];inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}inline bool topsort(){ queue
Q; Q.push(0); while(!Q.empty()){ int x=Q.front();Q.pop(); for(int i=head[x];i;i=nxt[i]){ int u=to[i]; if(!(--in[u]))Q.push(u); } } for(int i=1;i<=n;i++)if(in[i]>0)return false; return true;}struct data{ ll w;int s,x; bool operator <(const data &p)const{ if(w*p.s!=p.w*s)return w*p.s
Q;int cnt=0,b[N];inline int find(int x){return b[x]==x?x:b[x]=find(b[x]);}int main(){ freopen("perm.in","r",stdin); freopen("perm.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]),link(a[i],i),in[i]++,fa[i]=a[i]; for(int i=1;i<=n;i++)scanf("%d",&w[i]); if(!topsort()){puts("-1");return 0;} for(int i=1;i<=n;i++){ p[i]=(data){w[i],1,i}; Q.insert(p[i]);b[i]=i; } cnt=n;p[0].s=1; ll ans=0; data t; while(!Q.empty()){ t=*Q.begin();Q.erase(t); int y=find(fa[t.x]); ans+=t.w*p[y].s; if(y){ Q.erase(p[y]); data e=t; e.w+=p[y].w;e.s+=p[y].s;e.x=++cnt; b[cnt]=cnt;b[y]=cnt;b[find(t.x)]=cnt; fa[cnt]=fa[y];fa[t.x]=cnt; p[cnt]=e; Q.insert(e); } else b[find(t.x)]=0,p[0].s+=t.s; } cout<
<

转载于:https://www.cnblogs.com/Yuzao/p/8871713.html

你可能感兴趣的文章
跟随我在oracle学习php(8)
查看>>
Spring 3.1.0 Hibernate 3.0 Eclipse Spring WEB例子
查看>>
UVA-10212 The Last Non-zero Digit. 分解质因子+容斥定理
查看>>
求两个集合的交集,并集,差集
查看>>
Kotlin的语法糖(一)基础篇
查看>>
OkHttp源码分析
查看>>
让你的app体验更丝滑的11种方法!冲击手机应用榜单Top3指日可待
查看>>
windows kernel exploitation基础教程
查看>>
NS_OPTIONS枚举的用法
查看>>
java9系列(九)Make G1 the Default Garbage Collector
查看>>
QAQ高精度模板笔记√
查看>>
Jmeter计数器的使用-转载
查看>>
【Android笔记】入门篇02:全屏设置和禁止横屏竖屏切换
查看>>
Kubernetes的本质
查看>>
PL/SQL developer 管理多套数据库
查看>>
黑马程序员-分类(category)
查看>>
vue-cli多页面
查看>>
进程和线程
查看>>
iOS Foundation框架简介 -1.常用结构体的用法和输出
查看>>
libevent reference Mannual I
查看>>