zoukankan      html  css  js  c++  java
  • codeforces804D Expected diameter of a tree

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:codeforces804D

    正解:二分$+DP$

    解题报告:

      预处理出每个点所在的树内的最远点距离dis,考虑对于树$A$的点$x$,与树$B$的$y$产生的贡献就是$dis[x]+dis[y]+1$和两棵树的直径取一个$max$。

      对于$max$,我们显然可以分开考虑,当$dis[x]+dis[y]+1<$两棵树的直径,那么贡献就是直径的$max$。

      否则我们可以直接得到贡献。

      具体做法就是先对于每棵树内部的$dis$排序,然后每次枚举较小的连通块内的每个点,二分另一个连通块中的分界点位置就好了。

      看上去像个暴力,但是仔细想想,套上记忆化之后复杂度应该很靠谱,大概是根号左右。

    //It is made by ljh2000
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <queue>
    #include <cmath>
    #include <ctime>
    #include <map>
    #define lc root<<1
    #define rc root<<1|1
    #define reg(i,x) for(int i=first[x];i;i=nxt[i])
    using namespace std;
    typedef long long LL;
    const int MAXN = 200011;
    const int MAXM = 400011;
    int n,m,q,ecnt,first[MAXN],nxt[MAXM],to[MAXM],size[MAXN],bel[MAXN],cnt,f[MAXN][2],D[MAXN];
    double ans;
    map<int,double>mp[MAXN];
    vector<int>w[MAXN];
    vector<int>w2[MAXN];
    inline void link(int x,int y){ nxt[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; }
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void dfs(int x,int fa,int id){
    	bel[x]=id; size[id]++;
    	reg(i,x) {
    		int v=to[i]; if(v==fa) continue;
    		dfs(v,x,id);
    		if(f[v][0]+1>f[x][0]) f[x][1]=f[x][0],f[x][0]=f[v][0]+1;
    		else if(f[v][0]+1>f[x][1]) f[x][1]=f[v][0]+1;
    	}
    	D[id]=max(D[id],f[x][0]+f[x][1]);
    }
    
    inline void dfs2(int x,int fa,int maxl){
    	int tmp=max(maxl,f[x][0]);
    	w[ bel[x] ].push_back(tmp);
    	w2[ bel[x] ].push_back(0);
    	reg(i,x) {
    		int v=to[i]; if(v==fa) continue;
    		if(f[v][0]+1==f[x][0]) dfs2(v,x,max(maxl,f[x][1])+1);
    		else dfs2(v,x,max(maxl,f[x][0])+1);
    	}
    }
    
    inline int getp(int x,int val){
    	int l=0,r=w[x].size()-1,mid,pos;
    	if(val>w[x][r]) return r;
    	if(val<w[x][0]) return 0;
    	while(l<=r) {
    		mid=(l+r)>>1;
    		if(w[x][mid]<=val) pos=mid,l=mid+1;
    		else r=mid-1;
    	}
    	return pos+1;
    }
    
    inline void work(){
    	n=getint(); m=getint(); q=getint();	int x,y,r1,r2;
    	for(int i=1;i<=m;i++) {
    		x=getint(); y=getint();
    		link(x,y); link(y,x);
    	}	
    	
    	for(int i=1;i<=n;i++)
    		if(!bel[i]) {
    			dfs(i,0,++cnt);
    			dfs2(i,0,0);
    		}
    			
    	for(int i=1;i<=cnt;i++) sort(w[i].begin(),w[i].end());
    	for(int i=1;i<=cnt;i++) {
    		w2[i][ w2[i].size()-1 ]=w[i][ w[i].size()-1 ];
    		//printf("---%d
    ",w2[i][ w[i].size()-1 ]);
    		for(int j=w2[i].size()-2;j>=0;j--) {	
    		  w2[i][j]=w2[i][j+1]+w[i][j];
    		  //printf("---%d
    ",w2[i][j]);
    		}	
    	}
    			
    	while(q--) {
    		x=getint(); y=getint();
    		r1=bel[x]; r2=bel[y]; if(size[r1]>size[r2]) swap(r1,r2),swap(x,y);
    		if(mp[r1][r2]!=0) ans=mp[r1][r2];
    		else {
    			if(r1==r2) { puts("-1"); continue; }
    			int lim=max(D[r1],D[r2]),pos;
    			ans=0;
    			for(int i=0,ss=w[r1].size();i<ss;i++) {
    				pos=getp(r2,lim-1-w[r1][i]);
    				ans+=(double)pos*lim;
    				
    				if(pos<w[r2].size()) ans+=w2[r2][pos]+(w[r1][i]+1)*(w[r2].size()-pos);
    			}
    			ans/=size[r1];
    			ans/=size[r2];
    			mp[r1][r2]=ans;
    		}
    		printf("%.8lf
    ",ans);
    	}
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("804.in","r",stdin);
    	freopen("804.out","w",stdout);
    #endif
        work();
        return 0;
    }
    

      

  • 相关阅读:
    如何免费做一个属于自己稳定有效的图床
    关于自己每日计划是如何制定的
    记一次买4K显示器的心酸历程
    Mac常用的软件推荐
    2019 一整年的总结与一些个人反思
    Lucene学习笔记: 五,Lucene搜索过程解析
    Lucene学习笔记: 四,Lucene索引过程分析
    lucene学习笔记:三,Lucene的索引文件格式
    lucene学习笔记:二,Lucene的框架
    Lucene学习笔记:一,全文检索的基本原理
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6860080.html
Copyright © 2011-2022 走看看