BZOJ 1758: [Wc2010]重建计划 01分数规划+点分治+单调队列

code: 

#include <bits/stdc++.h>     
using namespace std; 
#define setIO(s) freopen(s".in","r",stdin)  
const int N=200006;  
const double eps=1e-6;     
const double inf=-100000000;              
struct node
{
    int u,dep,val; 
    node(int u=0,int dep=0,int val=0):u(u),dep(dep),val(val){}    
};     
struct data 
{
    int len; 
    double dis; 
    data(int len=0,double dis=0.0):len(len),dis(dis){}  
};   
bool cmp(node a,node b) { return a.dep<b.dep; }  
deque<data>q;        
vector<node>G[N];      
vector<int>tree[N];    
int n,L,R,edges,root; 
int hd[N],to[N<<1],nex[N<<1],val[N<<1];         
int size[N],mx[N],vis[N],sn,max_dep,RT;                 
double maxv[N],tmp[N],mid;
inline void add(int u,int v,int c) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;   
}              
void getroot(int u,int ff) 
{ 
    size[u]=1,mx[u]=0;  
    for(int i=hd[u];i;i=nex[i]) 
    {
        int v=to[i]; 
        if(v==ff||vis[v])    continue;   
        getroot(v,u);   
        size[u]+=size[v];   
        mx[u]=max(mx[u],size[v]);  
    }   
    mx[u]=max(mx[u],sn-size[u]);   
    if(mx[u]<mx[root])    root=u;      
}   
void getdis(int u,int ff,int d) 
{     
    max_dep=max(max_dep,d);  
    for(int i=hd[u];i;i=nex[i])   if(to[i]!=ff&&!vis[to[i]])    getdis(to[i],u,d+1);  
}
void prepare(int u) 
{ 
    vis[u]=1;             
    for(int i=hd[u];i;i=nex[i]) 
    {
        int v=to[i];  
        if(vis[v])    continue;                 
        max_dep=0; 
        getdis(v,u,1);                  
        G[u].push_back(node(v,max_dep,val[i]));                          
    }   
    sort(G[u].begin(),G[u].end(),cmp);    
    for(int i=hd[u];i;i=nex[i])  
    {
        int v=to[i]; 
        if(vis[v])    continue;
        sn=size[v];    
        root=0;   
        getroot(v,u);        
        tree[u].push_back(root);    
        prepare(root);  
    }
}    
void dfs(int u,int ff,int d,double dis) 
{   
    maxv[d]=max(maxv[d],dis);                        
    for(int i=hd[u];i;i=nex[i])  
    {
        int v=to[i]; 
        if(v==ff||vis[v])    continue;    
        dfs(v,u,d+1,dis+val[i]-mid);        
    }   
}  
int calculate(int u) 
{     
    int flag=0;    
    for(int i=0;i<G[u].size();++i) 
    {   
        int v=G[u][i].u;                   
        dfs(v,u,1,G[u][i].val-mid);       
        for(int j=1;j<=G[u][i].dep;++j)  if(maxv[j]>=-eps&&j>=L&&j<=R)   { flag=1;   break; }                                          
        if(i)      
        {
            int tl=min(R,G[u][i-1].dep);   
            for(int j=1;j<=min(R,G[u][i].dep);++j) 
            {                         
                for(;tl>=L-j&&tl>0;--tl)      
                {
                    while(!q.empty()&&(tmp[tl]-eps)>=q.front().dis) q.pop_front();                                  
                    q.push_front(data(tl,tmp[tl]));                                          
                }                  
                while(!q.empty()&&q.back().len>R-j)  q.pop_back(); 
                if(!q.empty()) 
                {                       
                    if(maxv[j]+q.back().dis>=-eps)  
                    {             
                        flag=1;              
                        break;  
                    }
                }
            }
        }
        while(!q.empty())    q.pop_front();   
        if(flag)    break;     
        for(int j=1;j<=G[u][i].dep;++j)   tmp[j]=max(tmp[j],maxv[j]); 
        for(int j=0;j<=G[u][i].dep;++j)   maxv[j]=inf;  
    }            
    if(G[u].size()) 
    {
        for(int i=0;i<=G[u][G[u].size()-1].dep;++i)   tmp[i]=maxv[i]=inf;            
    }  
    while(!q.empty())    q.pop_front();    
    return flag;                       
}
int solve(int u) 
{   
    vis[u]=1;   
    if(calculate(u))    return 1;      
    for(int i=0;i<tree[u].size();++i)      if(solve(tree[u][i]))   return 1;     
    return 0;   
}   
int main() 
{ 
    // setIO("input"); 
    int i,j;      
    scanf("%d%d%d",&n,&L,&R);         
    for(i=1;i<n;++i) 
    { 
        int x,y,z; 
        scanf("%d%d%d",&x,&y,&z); 
        add(x,y,z),add(y,x,z);  
    }          
    mx[0]=sn=n;   
    getroot(1,0);    
    RT=root;  
    prepare(root);       
    double l=0.0,r=1000000.0;       
    for(i=0;i<N;++i)   maxv[i]=tmp[i]=inf;       
    for(int i=33;i>=1;--i) 
    {
        mid=(l+r)/2;       
        memset(vis,0,sizeof(vis));        
        if(solve(RT))   
        {      
            l=mid;            
        }
        else 
        {     
            r=mid; 
        } 
    }                               
    printf("%.3f
",l);    
    return 0; 
}

  

原文地址:https://www.cnblogs.com/guangheli/p/11959569.html