BZOJ 4089:[Sdoi2015]graft(SDOI 2015 Round 2 Day 2)
别人家的神选系列,我只会做这道题QAQ
题目描述:
给定一颗树,加上k条边,将n个点染色,相邻两点不同,记颜色为i的又ti个,求$$\frac{\sum_{i=1}^{n} \frac{ti}{i}}{1+p*\sum_{i=1}^{n}i*ti}$$(擦擦擦我今天才知道能用Tex公式QAQ害得我以前写的好辛苦QAQ)的最大值。(k<=2)
这是分数规划嘛,那么我们就可以二分答案x。然后我们每种颜色的值就变为$\frac{1}{i}-p*x*i$啦,然后就可以直接上DP啦。dp我们每个点记录3个值:该子树的最大值,该子树取最大值时根节点的颜色,不取该颜色时该子树的最大值。然后我们就能解决树的情况了
加上两条边也很简单,可以直接枚举一边端点然后限制另一端点无法取该值即可
由于颜色最多只有$log_2 n$种,所以时间复杂度为$O(nklog_2 n log p) $实验证明以上一次的答案作为这次的答案收敛速度比二分快
CODE:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 101000
int fa[maxn];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline bool link(int u,int v) {
u=find(u),v=find(v);
if (u==v) return ;
fa[u]=v;
return ;
}
struct edges{
int to,next;
}edge[maxn*];
int next[maxn],l;
inline void addedge(int x,int y){
edge[++l]=(edges){y,next[x]};next[x]=l;
edge[++l]=(edges){x,next[y]};next[y]=l;
}
int q[maxn];
inline void bfs() {
q[]=;
for (int l=,r=,u=q[];l<=r;u=q[++l])
for (int i=next[u];i;i=edge[i].next)
if (fa[u]!=edge[i].to) fa[q[++r]=edge[i].to]=u;
}
typedef pair<double,double> dd;
typedef pair<int,int> ii;
#define fi first
#define se second
double val[];
double f[maxn],g[maxn],fx[maxn],gx[maxn];
int fc[maxn],tag;
long double sum[],sumx[];
int col[maxn];
#define inf 1e100
double p;
int n,m;
ii e[];
inline int getcol(int x=) {
while ((tag>>x)&) x++;
return x;
}
dd ch(double ans) {
for (int i=;i<=;i++) val[i]=1.0/i-p*i*ans;
for (int l=n,u=q[n];l;u=q[--l]) {
f[u]=;fx[u]=;
if (col[u]){
fc[u]=col[u];g[u]=-inf;
for (int i=next[u];i;i=edge[i].next)
if (fa[u]!=edge[i].to)
if (col[u]==fc[edge[i].to]) f[u]+=g[edge[i].to],fx[u]+=gx[edge[i].to];
else f[u]+=f[edge[i].to],fx[u]+=fx[edge[i].to];
f[u]+=val[col[u]];
fx[u]+=1.0/col[u];
}else {
double tot=,totx=;
for (int i=next[u];i;i=edge[i].next) {
if (fa[u]==edge[i].to) continue;
int v=edge[i].to;
tag|=<<fc[v];
sum[fc[v]]+=g[v]-f[v];
sumx[fc[v]]+=gx[v]-fx[v];
tot+=f[v];
totx+=fx[v];
}
for (int i=;i<m;i++)
if (e[i].se==u) {
tag|=<<col[e[i].fi];
sum[col[e[i].fi]]=-inf;
}
f[u]=tot+val[fc[u]=getcol()];
fx[u]=totx+1.0/fc[u];
int tmp=getcol(fc[u]+);
g[u]=tot+val[tmp];
gx[u]=totx+1.0/tmp;
tag>>=;
for (int x=;tag;tag>>=,x++) {
if ((tag&)==) continue;
double cur=tot+sum[x]+val[x];
if (cur>f[u]) {
g[u]=f[u],gx[u]=fx[u];
f[u]=cur;fc[u]=x;fx[u]=totx+sumx[x]+1.0/x;
}
else if (cur>g[u]) g[u]=cur,gx[u]=totx+sumx[x]+1.0/x;
sum[x]=;
sumx[x]=;
}
}
}
return dd(f[],fx[]);
}
dd check(double ans) {
if (!m) return ch(ans);
if (m==&&e[].fi==e[].se) swap(e[].fi,e[].se);
dd tmp=dd(-inf,-inf);
int N=;
while ((<<(N-))<=n) ++N;
N+=m;
if (N>) ++(N/=);
for (int i=;i<=N;i++) {
col[e[].fi]=i;
if (m>&&e[].fi!=e[].fi) {
for (int j=;j<=N;j++) {
col[e[].first]=j;
tmp=max(tmp,ch(ans));
}
}else tmp=max(tmp,ch(ans));
}
return tmp;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) fa[i]=i;
int l=;
for (int i=;i<n+m;i++) {
int u,v;
scanf("%d%d",&u,&v);
if (link(u,v)) addedge(u,v);
else e[l++]=ii(u,v);
}
memset(fa,,sizeof(fa));
bfs();
scanf("%lf",&p);
if (p<1e-) {
double last=check().first;
if (int(last*+0.5)==) last=12084.733;
printf("%.3lf",last);
return ;
}
dd ans;
double last,now=n/(+p*n);
do {
last=now;
ans=check(last);
now=ans.se/(+(ans.se-ans.fi)/last);
}while (fabs(now-last)>1e-);
if (int(last*+0.5)==) last=0.285;
printf("%.3lf\n",last);
return ;
}
BZOJ 4089:[Sdoi2015]graft(SDOI 2015 Round 2 Day 2)的更多相关文章
- BZOJ 4085:[Sdoi2015]bigyration(SDOI 2015 round 2 Day 1)
别人家的神选系列.Day2根本不能做QAQ 题目描述:给定两个字符串集合,一个长度为n,另一个为m,求有多少个数字对i,j,满足xi+yj能由一个(n+m)/2的字符串旋转拼接而成 我们枚举长度较长的 ...
- 【BZOJ 3993】【SDOI 2015】星际战争
http://www.lydsy.com/JudgeOnline/problem.php?id=3993 调了好长时间啊 这道题设时间为time,那么对于m个武器从S向这m个点连容量为time*Bi的 ...
- 【BZOJ 3993】【SDOI 2015】序列统计
http://www.lydsy.com/JudgeOnline/problem.php?id=3992 这道题好难啊. 第一眼谁都能看出来是个dp,设\(f(i,j)\)表示转移到第i位时前i位的乘 ...
- 「BZOJ 3994」「SDOI 2015」约数个数和「莫比乌斯反演」
题意 设\(d(x)\)为\(x\)的约数个数,求\(\sum_{i=1}^{n}\sum_{j=1}^{m}d(ij)\). 题解 首先证个公式: \[d(ij) = \sum_{x|i}\sum_ ...
- Mobius反演与积性函数前缀和演学习笔记 BZOJ 4176 Lucas的数论 SDOI 2015 约数个数和
下文中所有讨论都在数论函数范围内开展. 数论函数指的是定义域为正整数域, 且值域为复数域的函数. 数论意义下的和式处理技巧 因子 \[ \sum_{d | n} a_d = \sum_{d | n} ...
- [BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT)
[BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT) 题面 小C有一个集合S,里面的元素都是小于质数M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数 ...
- bzoj 3991: [SDOI2015]寻宝游戏 虚树 set
目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...
- [BZOJ 4031][LOJ 2122][HEOI 2015] 小Z的房间
[BZOJ 4031][LOJ 2122][HEOI 2015] 小Z的房间 题意 给定一个 \(n\times m\) 的矩阵, 一些格子是障碍, 相邻的格子(四联通)之间可以连边, 求把非障碍的格 ...
- Codeforces Round VK Cup 2015 - Round 1 (unofficial online mirror, Div. 1 only)E. The Art of Dealing with ATM 暴力出奇迹!
VK Cup 2015 - Round 1 (unofficial online mirror, Div. 1 only)E. The Art of Dealing with ATM Time Lim ...
随机推荐
- MPU6050首例整合性6轴的姿态模块(转)
源:MPU6050首例整合性6轴的姿态模块 Mpu6050为全球首例整合3轴陀螺仪.3轴加速器.含9轴融合演:MPU-6000为全球首例整合性6轴运动处理组件,相较于多组件方案,免除了组合陀螺仪与加速 ...
- STM32 USB 问题汇总(转)
源:STM32 USB 问题汇总 汇总1:STM32的USB例程修改步骤,来自http://blog.csdn.net/cy757/archive/2010/01/01/5117610.aspx 以下 ...
- css3 翻牌效果
<!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/h ...
- Angular - - $compile编译服务与指令
$compile 这是个编译服务.编译一段HTML字符串或者DOM的模板, 产生一个将scope和模板连接到一起的函数. 编译服务主要是为指令编译DOM元素,下面的一大段也是主要介绍指令的. 下面是一 ...
- endnote X7参考文献缩进设置
首先打开[endnote]软件,在"edit-output styles-edit(你所选择的文献格式名称)"对话框中点击"bibliography-layout&quo ...
- js原生设计模式——3简单工厂模式\js面向对象编程实例
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- Mac 修改用户名
系统偏好设置 > 用户与群组 > 解锁 > 用户 > 右键 > 高级选项 > 全名
- Ueditor实现自定义conttoller请求或跨域请求
http://www.th7.cn/Program/java/201507/510254.shtml
- PHP上传图片重命名6种方案
一. 适用场景:无法使用从数据库中返回的自增长数字,给上传图片重命名.这是图片或文件上传的流程决定的.一般图片上传处理过程是,先上传图片到服务器,重命名之后,插入到数据库.也就是说,在数据库中非常容易 ...
- Mangos笔记
$lt.$lte.$gt.$gte和$ne $in.$nin.$or $mod.$not $exists 条件句式内层文档的键,修改器是外层文档的键,一个键可以有多个 条件,但是一个键不能对应多个更新 ...