zoukankan      html  css  js  c++  java
  • luogu CF804D Expected diameter of a tree |Tarjan+樹的直徑+前綴和+二分查找

    题意翻译

    给一片森林,(q)个询问,每个询问两个点,问将这两个点所在的集合连接起来组成的新集合,它的最远两点的距离的期望值是多少。


    調了2個小時,終於好啦

    求出每個聯通快直徑的兩端點

    預處理每個點到最遠的點的距離

    排序,前綴和,快速計算

    #include<map>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=1e5+10;
    #define int long long
    #define db double
    inline int read(){
    	int x=0; char c=getchar();
    	while(c<'0'||c>'9')c=getchar();
    	while('0'<=c&&c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); }
    	return x;
    }
    int nxt[N<<1],head[N],go[N<<1],tot;
    inline void add(int u,int v){
    	nxt[++tot]=head[u],head[u]=tot,go[tot]=v;
    	nxt[++tot]=head[v],head[v]=tot,go[tot]=u;
    }
    int n,m,q;
    bool vis[N];
    int dfn[N],low[N],co[N],st[N],si[N],top,col,num;
    void Tarjan(int u){
    	st[++top]=u;
    	dfn[u]=low[u]=++num;
    	for(int i=head[u];i;i=nxt[i]){
    		int v=go[i];
    		if(!dfn[v]){
    			Tarjan(v);
    			low[u]=min(low[u],low[v]);
    		}else if(!co[v])
    		low[u]=min(low[u],dfn[v]);
    	}
    	if(dfn[u]==low[u]){
    		co[u]=++col;
    		si[col]=1;
    		while(st[top]!=u){
    			co[st[top]]=col;
    			si[col]++;
    			--top;
    		}	
    		--top;
    	}
    }
    int dis[N],all[N],coin[N],p,Max;
    void dfs(int u,int fa){
    	if(dis[u]>Max)Max=dis[u],p=u;
    	all[u]=max(all[u],dis[u]);
    	for(int i=head[u];i;i=nxt[i]){
    		int v=go[i];
    		if(v==fa)continue;
    		dis[v]=dis[u]+1;
    		dfs(v,u);
    	}
    }
    inline void findp(int u){
    	p=Max=-1; dfs(u,u); coin[co[u]]=max(coin[co[u]],Max);
    	Max=-1; dis[p]=0; dfs(p,p); coin[co[u]]=max(coin[co[u]],Max);
    	Max=-1; dis[p]=0; dfs(p,p); coin[co[u]]=max(coin[co[u]],Max);
    }
    vector<int>belong[N],Sum[N],e[N];
    map<pair<int,int>,db>IF;
    signed main(){
    	n=read(),m=read(),q=read();
    	for(int i=1;i<=m;i++)add(read(),read());
    	for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i);
    	for(int i=1;i<=n;i++){
    		if(!vis[co[i]])findp(i),vis[co[i]]=1;
    		belong[co[i]].push_back(i);
    	}
    	for(int i=1;i<=col;i++){
    		for(int j=0;j<belong[i].size();j++)e[i].push_back(all[belong[i][j]]);
    		sort(e[i].begin(),e[i].end());
    		for(int j=0;j<belong[i].size();j++){
    			Sum[i].push_back(e[i][j]);
    			if(j)Sum[i][j]+=Sum[i][j-1];
    		}
    	}
    	while(q--){
    		int a=co[read()],b=co[read()];
    		if(a==b){ printf("-1
    "); continue;}
    		if(IF[make_pair(a,b)]>0)
    		{ printf("%.9f
    ",IF[make_pair(a,b)]); continue; }
    		if(si[a]>si[b])swap(a,b);
    		int ans=0,op=belong[a].size()*belong[b].size();
    		int MAXN=max(coin[a],coin[b]);
    		for(int i=0;i<e[a].size();i++){
    			int A=e[a][i]+1;
    			int mzx=upper_bound(e[b].begin(),e[b].end(),MAXN-A)-e[b].begin();
    			ans+=MAXN*mzx;
    			if(mzx==0)ans+=A*e[b].size()+Sum[b][Sum[b].size()-1];
    			else ans+=A*(e[b].size()-mzx)+Sum[b][Sum[b].size()-1]-Sum[b][mzx-1];
    		}
    		db res=(db)ans/op;
    		IF[make_pair(b,a)]=IF[make_pair(a,b)]=res;
    		printf("%.10f
    ",res);
    	}
    }
    
  • 相关阅读:
    2016-8-29
    2016-8-25
    2016-8-24
    2016-8-23
    2016-8-22
    2016-8-16
    2016-8-15
    深圳_多测师面试 __腾讯云/_高级讲师肖sir
    深圳_多测师面试 _新字节跳动(2020年10月23日)_高级讲师肖sir
    多测师讲解自动化 _RF_(202)高级讲师肖sir
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/12693052.html
Copyright © 2011-2022 走看看