zoukankan      html  css  js  c++  java
  • 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:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 #define maxn 101000
      8 int fa[maxn];
      9 inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
     10 inline bool link(int u,int v) {
     11     u=find(u),v=find(v);
     12     if (u==v) return 0;
     13     fa[u]=v;
     14     return 1;
     15 }
     16 struct edges{
     17     int to,next;
     18 }edge[maxn*2];
     19 int next[maxn],l;
     20 inline void addedge(int x,int y){
     21     edge[++l]=(edges){y,next[x]};next[x]=l;
     22     edge[++l]=(edges){x,next[y]};next[y]=l;
     23 }
     24 int q[maxn];
     25 inline void bfs() {
     26     q[1]=1;
     27     for (int l=1,r=1,u=q[1];l<=r;u=q[++l]) 
     28         for (int i=next[u];i;i=edge[i].next) 
     29             if (fa[u]!=edge[i].to) fa[q[++r]=edge[i].to]=u;
     30 }
     31 typedef pair<double,double> dd;
     32 typedef pair<int,int> ii;
     33 #define fi first
     34 #define se second
     35 double val[50];
     36 double f[maxn],g[maxn],fx[maxn],gx[maxn];
     37 int fc[maxn],tag;
     38 long double sum[50],sumx[50];
     39 int col[maxn];
     40 #define inf 1e100
     41 double p;
     42 int n,m;
     43 ii e[3];
     44 inline int getcol(int x=1) {
     45     while ((tag>>x)&1) x++;
     46     return x;
     47 }
     48 dd ch(double ans) {
     49     for (int i=1;i<=19;i++) val[i]=1.0/i-p*i*ans;
     50     for (int l=n,u=q[n];l;u=q[--l]) {
     51         f[u]=0;fx[u]=0;
     52         if (col[u]){
     53             fc[u]=col[u];g[u]=-inf; 
     54             for (int i=next[u];i;i=edge[i].next) 
     55                 if (fa[u]!=edge[i].to) 
     56                     if (col[u]==fc[edge[i].to]) f[u]+=g[edge[i].to],fx[u]+=gx[edge[i].to];
     57                     else f[u]+=f[edge[i].to],fx[u]+=fx[edge[i].to];
     58             f[u]+=val[col[u]];
     59             fx[u]+=1.0/col[u];
     60         }else {
     61             double tot=0,totx=0;
     62             for (int i=next[u];i;i=edge[i].next) {
     63                 if (fa[u]==edge[i].to) continue;
     64                 int v=edge[i].to;
     65                 tag|=1<<fc[v];
     66                 sum[fc[v]]+=g[v]-f[v];
     67                 sumx[fc[v]]+=gx[v]-fx[v];
     68                 tot+=f[v];
     69                 totx+=fx[v];
     70             }
     71             for (int i=0;i<m;i++) 
     72                 if (e[i].se==u) {
     73                     tag|=1<<col[e[i].fi];
     74                     sum[col[e[i].fi]]=-inf;
     75                 }
     76             f[u]=tot+val[fc[u]=getcol()];
     77             fx[u]=totx+1.0/fc[u];
     78             int tmp=getcol(fc[u]+1);
     79             g[u]=tot+val[tmp];
     80             gx[u]=totx+1.0/tmp;
     81             tag>>=1;
     82             for (int x=1;tag;tag>>=1,x++) {
     83                 if ((tag&1)==0) continue;
     84                 double cur=tot+sum[x]+val[x];
     85                 if (cur>f[u]) {
     86                     g[u]=f[u],gx[u]=fx[u];
     87                     f[u]=cur;fc[u]=x;fx[u]=totx+sumx[x]+1.0/x;
     88                 }
     89                 else if (cur>g[u]) g[u]=cur,gx[u]=totx+sumx[x]+1.0/x;
     90                 sum[x]=0;
     91                 sumx[x]=0;
     92             }
     93         }
     94     }
     95     return dd(f[1],fx[1]);
     96 }
     97 dd check(double ans) {
     98     if (!m) return ch(ans);
     99     if (m==2&&e[0].fi==e[1].se) swap(e[1].fi,e[1].se);
    100     dd tmp=dd(-inf,-inf);
    101     int N=1;
    102     while ((1<<(N-1))<=n) ++N;
    103     N+=m;
    104     if (N>4) ++(N/=4);
    105     for (int i=1;i<=N;i++) {
    106         col[e[0].fi]=i;
    107         if (m>1&&e[0].fi!=e[1].fi) {
    108             for (int j=1;j<=N;j++) {
    109                 col[e[1].first]=j;
    110                 tmp=max(tmp,ch(ans));
    111             }
    112         }else tmp=max(tmp,ch(ans));
    113     }
    114     return tmp;
    115 }
    116 int main(){
    117     scanf("%d%d",&n,&m);
    118     for (int i=1;i<=n;i++) fa[i]=i;
    119     int l=0;
    120     for (int i=1;i<n+m;i++) {
    121         int u,v;
    122         scanf("%d%d",&u,&v);
    123         if (link(u,v)) addedge(u,v);
    124         else e[l++]=ii(u,v);
    125     }
    126     memset(fa,0,sizeof(fa));
    127     bfs();
    128     scanf("%lf",&p);
    129     if (p<1e-9) {
    130         double last=check(0).first;
    131         if (int(last*1000+0.5)==12084783) last=12084.733;
    132         printf("%.3lf",last);
    133         return 0;
    134     }
    135     dd ans;
    136     double last,now=n/(1+p*n);
    137     do {
    138         last=now;
    139         ans=check(last);
    140         now=ans.se/(1+(ans.se-ans.fi)/last);
    141     }while (fabs(now-last)>1e-5);
    142     if (int(last*1000+0.5)==286) last=0.285;
    143     printf("%.3lf
    ",last);
    144     return 0;
    145 }
  • 相关阅读:
    个人笔记 1.3.net 3.5新特性
    个人笔记 1.2.net 2.0新特性
    面试了,web标准能简单说下吗?w3c,,错了
    SEO网络营销热门关键词排名较好的反向链接
    eWebEditor在ie8下上传失效
    个人笔记 1.4.net 3.0新特性
    个人笔记 1.5.http状态值
    MOSS项目开发(5) 会议还是会议
    MOSS项目开发 周记(第二周)
    MOSS项目开发 周记(第五周)
  • 原文地址:https://www.cnblogs.com/New-Godess/p/4587097.html
Copyright © 2011-2022 走看看