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 ...
随机推荐
- IOS开发中使用CNContact\CNMutableContact 对通讯录增删改查
IOS开发中使用CNContact\CNMutableContact 对通讯录增删改查 首先当然是把CNcontact包含在工程中: @import Contacts; 1.下面是增加联系人的程序段: ...
- RabbitMQ消息队列(三):任务分发机制
在上篇文章中,我们解决了从发送端(Producer)向接收端(Consumer)发送“Hello World”的问题.在实际的应用场景中,这是远远不够的.从本篇文章开始,我们将结合更加实际的应用场景来 ...
- linux与windows回车换行符的区别
转自:http://www.cnblogs.com/dartagnan/archive/2010/12/14/2003499.html “回车”(carriage return)VS “换行”(li ...
- java制作图片水印
1.创建缓存图片对象 2.创建Java绘图工具对象 3.将原图绘制到缓存图片对象 4.使用工具将水印绘制到缓存图片对象 5.创建图片编码工具类 6.输出缓存图片对象到目标图片文件 BufferedIm ...
- Struts2的那些小细节
1.result中传多个参数,&不允许使用需要转义&即多个参数之间用&隔开 <result type="redirectAction">show ...
- mysql中游标的使用案例详解(学习笔记)
1.游标是啥玩意?简单的说:游标(cursor)就是游动的标识,啥意思呢,通俗的这么说,一条sql取出对应n条结果资源的接口/句柄,就是游标,沿着游标可以一次取出一行.我给大家准备一张图: 2.怎么使 ...
- html bottom html submit按钮表单控件与CSS美化
一.html submit与bottom按钮基本语法结构 1.html submit按钮在input标签里设置type="submit"即可设置此表单控件为按钮. submit按钮 ...
- angular2教程
https://github.com/lewis617/angular2-tutorial
- HDU-2058-The sum problem(数学题技巧型)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2058 思路: 这题的n,m都很大,很显然直接暴力,会超时,那就不能全部都找了,利用等差数列求和公式, ...
- HDU-1395-2^x mod n = 1(数学题(二次出错))
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1395 这题一定要滴水不漏的把所有代码全部看完. 这个题目是一个数学类型的题,我也没思路,只知道n== ...