zoukankan      html  css  js  c++  java
  • CF566C Logistical Questions

    分析

    首先,设 (d(i,j)) 表示当前定义下 i,j 的距离,然后可以发现,当 j 固定,i 在一条路径上移动时,(d) 是下凸函数,就是说只会有一个最优解。。

    然后考虑 (f(i)),表示以 i 为重心时的答案。

    有:(f(i)=sum_{j eq i}f(i,j))

    然后由于下凸函数相加后也为下凸函数,所以 (f(i)) 也为下凸函数。

    所以全树只有一个最优位置(不一定为节点),且从此扩散出去的点的答案会变大。

    于是考虑链的情况,二分就完事了。

    然后放到树上,就可以点分治,每次在根的相邻节点中选出会使答案变小的方向,继续点分。

    然后显然我们不能每次都暴力计算 (f),我们可以利用导数来快速计算。

    注意

    codeforces 好像不可以用 long double。。

    然后最大值要算好设。。。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+7;
    template <class I>
    inline void read(I &x){
        int f=1;
        char c;
        for(c=getchar();c<'0'||c>'9';c=getchar()) if(c=='-') f=-1;
        for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+(c&15),c=getchar());
        x*=f;
    }
    int n,w[N];
    int head[N],nxt[2*N],ver[2*N],edge[2*N],tot=1;
    inline void add(int x,int y,int z){
    	ver[++tot]=y,edge[tot]=z,nxt[tot]=head[x],head[x]=tot;
    }
    double res=0;
    int rt=0,d[N],sz;
    bool v[N];
    void getsz(int x,int f){
    	d[x]=1;
    	for(int i=head[x];i;i=nxt[i]){
    		int y=ver[i];
    		if(v[y]||y==f) continue;
    		getsz(y,x);
    		d[x]+=d[y];
    	}
    }
    void getrt(int x,int f){
    	d[x]=1;
    	int mx=0;
    	for(int i=head[x];i;i=nxt[i]){
    		int y=ver[i];
    		if(v[y]||y==f) continue;
    		getrt(y,x);
    		d[x]+=d[y];
    		if(d[y]>mx) mx=d[y];
    	}
    	mx=max(mx,sz-d[x]);
    	if(mx<=sz/2) rt=x;
    }
    double ds[N];
    void calc(int o,int x,int fa,int dis){
    	res+=(double)pow(dis,1.5)*w[x];
    	ds[o]+=1.5*pow(dis,0.5)*w[x];
    	for(int i=head[x];i;i=nxt[i]){
    		int y=ver[i];
    		if(y==fa) continue;
    		calc(o,y,x,dis+edge[i]);
    	}
    }
    int anss;
    double ans=1e20;
    void dfs(int x){
    	getsz(x,0);
    	sz=d[x];
    	getrt(x,0);
    	if(v[x]) return;
    	v[x=rt]=1;
    	res=0;
    	double sds=0;
    	for(int i=head[x];i;i=nxt[i]){
    		int y=ver[i];
    		ds[y]=0;
    		calc(y,y,x,edge[i]);
    		sds+=ds[y];		
    	}
    	if(ans>res) ans=res,anss=x;
    	for(int i=head[x];i;i=nxt[i]){
    		int y=ver[i];
    		if(sds-2*ds[y]>=0) continue;
    		dfs(y);
    		return;
    	}
    }
    int main(){
    	read(n);
    	for(int i=1;i<=n;i++) read(w[i]);
    	for(int i=1;i<n;i++){
    		int x,y,z;
    		read(x),read(y),read(z);
    		add(x,y,z);
    		add(y,x,z);
    	}
    	dfs(1);
    	printf("%d %.7f
    ",anss,ans);
    	return 0;
    }
    
  • 相关阅读:
    UVA 254 Towers of Hanoi
    UVA 701 The Archeologists' Dilemma
    UVA 185 Roman Numerals
    UVA 10994 Simple Addition
    UVA 10570 Meeting with Aliens
    UVA 306 Cipher
    UVA 10160 Servicing Stations
    UVA 317 Hexagon
    UVA 10123 No Tipping
    UVA 696 How Many Knights
  • 原文地址:https://www.cnblogs.com/Hikigaya/p/11975481.html
Copyright © 2011-2022 走看看