[Wc2010]重建计划
Time Limit: 40 Sec Memory Limit: 162 MB
Submit: 4345 Solved: 1054
[Submit][Status][Discuss]
Description
Input
第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限
接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai,Bi,Vi分别表示道路(Ai,Bi),其价值为Vi 其中城市由1..N进行标号
Output
输出最大平均估值,保留三位小数
Sample Input
4
2 3
1 2 1
1 3 2
1 4 3
2 3
1 2 1
1 3 2
1 4 3
Sample Output
2.500
HINT
N<=100000,1<=L<=U<=N-1,Vi<=1000000 新加数据一组 By leoly,但未重测..2016.9.27
题解:点分上是一个log,二分是一个log,然后是单调队列判断,n,总复杂度O(nlogn^2)
hzwer的代码十分不优秀,应该是按照最低深度从小到大去个棵子树去判断才可以,不然是不行的,
不然会是复杂度退化成n^2
改了比较siz还是T,不知道为什么了。
1 #include<cstring> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdio> 6 #include<cstdlib> 7 #include<vector> 8 9 #define inf 1000000007 10 #define eps 0.0001 11 #define N 100007 12 #define M 200007 13 #define ll long long 14 using namespace std; 15 inline int read() 16 { 17 int x=0,f=1;char ch=getchar(); 18 while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 19 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 23 int n,S,L,U,rt,lim; 24 double ans; 25 int cnt,hed[N],rea[M],val[M],nxt[M]; 26 int sz[N],fa[N],f[N],dep[N]; 27 int q[N],dq[N]; 28 bool flag[N]; 29 double dis[N],mx[N]; 30 int num[N*10],xz,shu[N*10]; 31 32 void add(int u,int v,int w) 33 { 34 nxt[++cnt]=hed[u]; 35 hed[u]=cnt; 36 rea[cnt]=v; 37 val[cnt]=w; 38 } 39 void get_root(int u,int fa) 40 { 41 sz[u]=1,f[u]=0; 42 for (int i=hed[u];i!=-1;i=nxt[i]) 43 { 44 int v=rea[i]; 45 if (v==fa||flag[v]) continue; 46 get_root(v,u); 47 sz[u]+=sz[v]; 48 f[u]=max(f[u],sz[v]); 49 } 50 f[u]=max(f[u],S-sz[u]); 51 if (f[u]<=f[rt])rt=u; 52 } 53 bool check(int rt,double zhi) 54 { 55 int up=0; 56 for (int i=hed[rt];i!=-1;i=nxt[i]) 57 { 58 int v=rea[i];double fee=(double)val[i]-zhi; 59 if (flag[v])continue; 60 int hd=0,tl=1; 61 q[0]=v; 62 fa[v]=rt,dep[v]=1; 63 dis[v]=fee; 64 while(hd!=tl) 65 { 66 int now=q[hd];hd++; 67 for (int i=hed[now];i!=-1;i=nxt[i]) 68 { 69 int v=rea[i];double fee=(double)val[i]-zhi; 70 if (v==fa[now]||flag[v])continue; 71 q[tl++]=v; 72 fa[v]=now,dep[v]=dep[now]+1; 73 dis[v]=dis[now]+fee; 74 } 75 } 76 int l=1,r=0,now=up; 77 for (int i=0;i<tl;i++) 78 { 79 int x=q[i]; 80 while(dep[x]+now>=L&&now>=0) 81 { 82 while(l<=r&&mx[dq[r]]<mx[now])r--; 83 dq[++r]=now; 84 now--; 85 } 86 while(l<=r&&dep[x]+dq[l]>U)l++; 87 if (l<=r&&dis[x]+mx[dq[l]]>=0)return 1; 88 } 89 for (int i=up+1;i<=dep[q[tl-1]];i++)mx[i]=-inf; 90 for (int i=0;i<tl;i++) 91 { 92 int x=q[i]; 93 mx[dep[x]]=max(mx[dep[x]],dis[x]); 94 } 95 up=max(up,dep[q[tl-1]]); 96 } 97 return 0; 98 } 99 void cal(int u)//可以 100 { 101 double l=ans,r=lim,mid; 102 while(r-l>eps) 103 { 104 mid=(l+r)/2; 105 if(check(u,mid))l=mid; 106 else r=mid; 107 } 108 ans=l; 109 } 110 bool cmp(int x,int y) 111 { 112 return shu[x]<shu[y]; 113 } 114 void solve(int u) 115 { 116 cal(u); 117 flag[u]=1;int yl=xz,Sum=S; 118 for (int i=hed[u];i!=-1;i=nxt[i]) 119 { 120 int v=rea[i]; 121 if (flag[v])continue; 122 rt=0; 123 if (sz[v]<sz[u])S=sz[v]; 124 else S=Sum-sz[u]; 125 get_root(v,0); 126 if(sz[v]>L)num[++xz]=rt,shu[++xz]=S; 127 } 128 sort(num+yl+1,num+xz+1,cmp); 129 for (int i=yl+1;i<=xz;i++) 130 solve(num[i]); 131 xz=yl; 132 } 133 int main() 134 { 135 memset(hed,-1,sizeof(hed)); 136 n=read(),L=read(),U=read(); 137 for (int i=1;i<n;i++) 138 { 139 int u=read(),v=read(),w=read(); 140 add(u,v,w),add(v,u,w); 141 lim=max(lim,w); 142 } 143 f[0]=n; 144 rt=0,S=n; 145 get_root(1,0); 146 solve(rt); 147 printf("%.3lf",ans); 148 }