Description

Solution

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

考虑这个排列 \(p\),编号为 \(a[i]\) 的出现了,\(i\) 才可以出现

那么如果连边 \((a[i],i)\),就会构成一棵以 \(0\) 为根的树,每一个点只有一个父亲

否则就不合法

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

要求的就是代价最大的一个拓扑序

那么问题就和 \(POJ\,2054\) 一样的做法了,用一个神奇的贪心

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

答案加上被合并的点的权值乘以父亲的 \(size\)

正确性感性理解一下,具体证明和国王游戏差不多,发现 \(swap\) 之后不会更优

实现可以用一个堆或者 \(set\) 实现

然而 \(set\) 被卡常了,开 \(O2\) 才能过

#include<bits/stdc++.h>
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<int>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<p.w*s;
return x<p.x;
}
}p[N];
set<data>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<<ans<<endl;
return 0;
}

bzoj 5289: [Hnoi2018]排列的更多相关文章

  1. 5289: [Hnoi2018]排列

    5289: [Hnoi2018]排列 链接 分析: 首先将题意转化一下:每个点向a[i]连一条边,构成了一个以0为根节点的树,要求选一个拓扑序,点x是拓扑序中的第i个,那么价值是i*w[x].让价值最 ...

  2. 【BZOJ5289】[HNOI2018]排列(贪心)

    [BZOJ5289][HNOI2018]排列(贪心) 题面 BZOJ 洛谷 题解 这个限制看起来不知道在干什么,其实就是找到所有排列\(p\)中,\(p_k=x\),那么\(k<j\),其中\( ...

  3. BZOJ.5289.[AHOI/HNOI2018]排列(贪心 heap)

    BZOJ LOJ 洛谷 \(Kelin\)写的挺清楚的... 要求如果\(a_{p_j}=p_k\),\(k\lt j\),可以理解为\(k\)要在\(j\)之前选. 那么对于给定的\(a_j=k\) ...

  4. [BZOJ 1072] [SCOI2007] 排列perm 【状压DP】

    题目链接:BZOJ 1072 这道题使用 C++ STL 的 next_permutation() 函数直接暴力就可以AC .(使用 Set 判断是否重复) 代码如下: #include <io ...

  5. BZOJ 4517: [Sdoi2016]排列计数

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 911  Solved: 566[Submit][Status ...

  6. BZOJ 1072: [SCOI2007]排列perm 状态压缩DP

    1072: [SCOI2007]排列perm Description 给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0).例如123434有90种排列能被2整除,其中末位为 ...

  7. BZOJ 1072 [SCOI2007]排列perm

    1072: [SCOI2007]排列perm Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1268  Solved: 782[Submit][Sta ...

  8. 数学(错排):BZOJ 4517: [Sdoi2016]排列计数

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 693  Solved: 434[Submit][Status ...

  9. BZOJ 4517: [Sdoi2016]排列计数 [容斥原理]

    4517: [Sdoi2016]排列计数 题意:多组询问,n的全排列中恰好m个不是错排的有多少个 容斥原理强行推♂倒她 $恰好m个不是错排 $ \[ =\ \ge m个不是错排 - \ge m+1个不 ...

随机推荐

  1. alpha-咸鱼冲刺day2-紫仪

    总汇链接 一,合照 emmmmm.自然是没有的. 二,项目燃尽图 三,项目进展 今天并没有什么进展,弄了好久好像也只研究出怎么把JS的功能块插入进去.html的信息提交这些还不知道要怎么弄. 四,问题 ...

  2. PTA題目的處理(二)

    題目7-1 計算分段函數[1] 1.實驗代碼 #include <stdio.h> int main() { float x,y; scanf("%f",&x) ...

  3. Python 迭代器之列表解析

     [TOC] 尽管while和for循环能够执行大多数重复性任务, 但是由于序列的迭代需求如此常见和广泛, 以至于Python提供了额外的工具以使其更简单和高效. 迭代器在Python中是以C语言的 ...

  4. prop attr 到底哪里不一样?

    好吧 首先承认错误  说好的每天进行一次只是总结  但是我没坚持住 准确的来说 我并没有每天会学到了东西 但是 我一直在持续努力着  以后应该不会每天都写  但是自己觉得有用的  或者想加强记忆的 可 ...

  5. 2-51单片机WIFI学习(开发板测试远程通信详细介绍)

    前一篇链接(最后有APP安装包下载地址) http://www.cnblogs.com/yangfengwu/p/8720148.html 由于自己别的贴片的板子还没到,所以用自己的8266最小系统板 ...

  6. Mego开发文档 - 保存关系数据

    保存关系数据 由于没有对象的更改跟踪,因此关系的操作需要开发者明确指定,在成功执行后Mego会影响到相应的关系属性中. 添加关系 在以下示例中如果成功执行则source的Customer属性会变为ta ...

  7. zuul入门(4)zuul的注解@EnableZuulServer和@EnableZuulProxy

    @EnableZuulServer.@EnableZuulProxy两个注解 @EnableZuulProxy简单理解为@EnableZuulServer的增强版,当Zuul与Eureka.Ribbo ...

  8. python入门(11)条件判断和循环

    python入门(11)条件判断和循环 条件判断 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断. 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现: ag ...

  9. 您的 Java 代码安全吗 — 还是暴露在外? 【转】

    在开发 Java Web 应用程序时,您需要确保应用程序拥有完善的安全性特征补充.这里在谈到 Java 安全性时,我们并不谈及 Java 语言提供的安全性 API,也不涉及使用 Java 代码来保护应 ...

  10. 双击表,powerdesigner pdm 没有 comment列(no comment)