# BZOJ 4089:[Sdoi2015]graft(SDOI 2015 Round 2 Day 2)

别人家的神选系列，我只会做这道题QAQ

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);
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\n",last);
144     return 0;
145 }

posted @ 2015-06-18 21:41  New_Godess  阅读(...)  评论(...编辑  收藏