别人家的神选系列,我只会做这道题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)的更多相关文章

  1. BZOJ 4085:[Sdoi2015]bigyration(SDOI 2015 round 2 Day 1)

    别人家的神选系列.Day2根本不能做QAQ 题目描述:给定两个字符串集合,一个长度为n,另一个为m,求有多少个数字对i,j,满足xi+yj能由一个(n+m)/2的字符串旋转拼接而成 我们枚举长度较长的 ...

  2. 【BZOJ 3993】【SDOI 2015】星际战争

    http://www.lydsy.com/JudgeOnline/problem.php?id=3993 调了好长时间啊 这道题设时间为time,那么对于m个武器从S向这m个点连容量为time*Bi的 ...

  3. 【BZOJ 3993】【SDOI 2015】序列统计

    http://www.lydsy.com/JudgeOnline/problem.php?id=3992 这道题好难啊. 第一眼谁都能看出来是个dp,设\(f(i,j)\)表示转移到第i位时前i位的乘 ...

  4. 「BZOJ 3994」「SDOI 2015」约数个数和「莫比乌斯反演」

    题意 设\(d(x)\)为\(x\)的约数个数,求\(\sum_{i=1}^{n}\sum_{j=1}^{m}d(ij)\). 题解 首先证个公式: \[d(ij) = \sum_{x|i}\sum_ ...

  5. Mobius反演与积性函数前缀和演学习笔记 BZOJ 4176 Lucas的数论 SDOI 2015 约数个数和

    下文中所有讨论都在数论函数范围内开展. 数论函数指的是定义域为正整数域, 且值域为复数域的函数. 数论意义下的和式处理技巧 因子 \[ \sum_{d | n} a_d = \sum_{d | n} ...

  6. [BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT)

    [BZOJ 3992] [SDOI 2015] 序列统计(DP+原根+NTT) 题面 小C有一个集合S,里面的元素都是小于质数M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数 ...

  7. bzoj 3991: [SDOI2015]寻宝游戏 虚树 set

    目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...

  8. [BZOJ 4031][LOJ 2122][HEOI 2015] 小Z的房间

    [BZOJ 4031][LOJ 2122][HEOI 2015] 小Z的房间 题意 给定一个 \(n\times m\) 的矩阵, 一些格子是障碍, 相邻的格子(四联通)之间可以连边, 求把非障碍的格 ...

  9. 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 ...

随机推荐

  1. MAC上更攺jenkins默认安装目录

    /Library/LaunchDaemons #编缉里面的jenkinshome和username sudo vim org.jenkins-ci.plist #然后 sudo launchctl u ...

  2. PHP的高并发和大数据处理

    收集前人的经验.加速学习,解决工作中的难题. 一.代码优化(包括sql语句的优化), 合理的使用索引,避免整表查询.二.日常海量数据处理我用文件缓存,文件缓存分两种,第一种是最常见的生成html静太文 ...

  3. JDBC executeBatch 抛出异常停止

    进行批量更新的时候发现: addBatch(sql); executeBatch 抛出异常后,剩余的sql没有更新,即出现异常之前的都入库了,异常之后即使有可执行sql都不会执行. 百度资料后了解:这 ...

  4. UVa 908 - Re-connecting Computer Sites

    题目大意:有n个网站,由m条线路相连,每条线路都有一定的花费,找出连接所有线路的最小花费. 最小生成树问题(Minimal Spanning Tree, MST),使用Kruskal算法解决. #in ...

  5. 安卓Visibility属性

    可见(visible) XML文件:android:visibility="visible" Java代码:view.setVisibility(View.VISIBLE); 不可 ...

  6. spark中数据的读取与保存

    1.文本文件 (1)读取文本文件 JavaRDD<String> input =sc.textFile(dir) (2)保存文本文件 result.saveAsTextFile(dir)) ...

  7. javaEE开发中使用session同步和token机制来防止并发重复提交

    javaEE开发中使用session同步和token机制来防止并发重复提交 通常在普通的操作当中,我们不需要处理重复提交的,而且有很多方法来防止重复提交.比如在登陆过程中,通过使用redirect,可 ...

  8. Javascript教程:js异步模式编程的4种解决方法

    随着人们对网站视觉效果及用户体验的要求越来越高,所以在未来网站的建设中,设计师们开始越来越多的使用了js文件来达到预期的效果,随着js文件的越来越多,令设计师们最头痛的事情也就来了,那就是Javasc ...

  9. delphi公用函数

    {*******************************************************} { } { Delphi公用函数单元 } { } { 版权所有 (C) 2008 } ...

  10. jQuery 处理TextArea

    jQuery 处理TextArea: $('#btn001').click(function(e) { console.log("btn001Click"); var cmt = ...