• 【未知来源】Happy


    题意

      给出一个 (n) 个节点的树,两点之间有且仅有一条路径相连。
      给出 (m) 个点对 (x_i,y_i),如果添加一条双向边 ((u,v))(x_i)(y_i) 在一个简单环中,则称这条边是 happy 的,happy 值为这个简单环的点数。
      请你求出对于点对 (x_i,y_i),所有 happy 的边的 happy 值的平均数。
      注意,出题人似乎认为简单环是包括自环的。
      (n,mle 100000)

    题解

      什么普及组傻逼题,画个朴素的 (x,y≠lca) 的情况就知道是合并两棵子树的信息了,(x=lca)(y=lca) 的情况同理。( ext{dfs}) 预处理就好。
      但是细节比较复杂,写得我要死……尤其是题目告诉你简单环包括自环,你就应该能猜到可能有 (x_i=y_i) 的情况了,这种情况你要 (O(n)) 合并若干棵子树而不是两棵子树的信息,多预处理一些信息就好了。
      考场上写+调了两个小时才 1A(没拍),自己还是太菜了,下次争取一小时 1A 吧。

    #include<bits/stdc++.h>
    #define int long long
    #define N 100002
    using namespace std;
    inline int read(){
    	int x=0; bool f=1; char c=getchar();
    	for(;!isdigit(c); c=getchar()) if(c=='-') f=0;
    	for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
    	if(f) return x;
    	return 0-x;
    }
    int n,m;
    struct edge{int v,nxt;}e[N<<1];
    int hd[N],cnt;
    inline void add(int u, int v){e[++cnt]=(edge){v,hd[u]}, hd[u]=cnt;}
    int fa[N][20],dep[N];
    double spcans[N]; int sum[N],siz[N],spcsum[N],spcpair[N];
    void dfs1(int u, int f){
    	fa[u][0]=f, dep[u]=dep[f]+1, sum[u]=siz[u]=1;
    	for(int i=1; i<=17; ++i) fa[u][i]=fa[fa[u][i-1]][i-1];
    	int presum=0, presiz=0;
    	for(int i=hd[u]; i; i=e[i].nxt) if(e[i].v!=f){
    		dfs1(e[i].v,u);
    		sum[u]+=sum[e[i].v]+siz[e[i].v], siz[u]+=siz[e[i].v];
    		spcans[u]+=presum*siz[e[i].v]+sum[e[i].v]*presiz;
    		spcpair[u]+=siz[e[i].v]*presiz;
    		presum+=sum[e[i].v], presiz+=siz[e[i].v];
    	}
    	spcsum[u]=presum;
    }
    int outsum[N];
    void dfs2(int u, int os){
    	outsum[u]=os;
    	for(int i=hd[u]; i; i=e[i].nxt) if(e[i].v!=fa[u][0])
    		dfs2(e[i].v, os+siz[1]-siz[u] + sum[u]-sum[e[i].v]-siz[e[i].v]);
    }
    int tag;
    int getLca(int x, int y){
    	//if(dep[x]<dep[y]) swap(x,y);
    	if(dep[x]>dep[y]){
    		for(int i=17; i>=0; --i) if(dep[fa[x][i]]>dep[y]) x=fa[x][i];
    		tag=x, x=fa[x][0];
    	}
    	if(x==y) return x;
    	for(int i=17; i>=0; --i) if(fa[x][i]^fa[y][i]) x=fa[x][i], y=fa[y][i];
    	tag=x;
    	return fa[x][0];
    }
    signed main(){
    	//freopen("a.in","r",stdin);
    	n=read(), m=read();
    	int u,v;
    	for(int i=1; i<n; ++i) u=read(), v=read(), add(u,v), add(v,u);
    	dfs1(1,0), dfs2(1,0);
    	for(int i=1; i<=m; ++i){
    		u=read(), v=read();
    		if(dep[u]<dep[v]) swap(u,v); 
    		int lca=getLca(u,v);
    		if(u==v){
    			//cout<<spcans[u]<<' '<<spcsum[u]<<' '<<(siz[1]-siz[u])<<' '<<outsum[u]*(siz[u]-1)<<' '<<spcsum[u]+outsum[u]<<endl;
    			printf("%.7lf
    ", (double)(spcans[u] + spcsum[u]*(siz[1]-siz[u])+outsum[u]*(siz[u]-1) + spcsum[u]+outsum[u]) / (spcpair[u]+(siz[u]-1)*(siz[1]-siz[u]) + siz[1]) + 1);
    		}
    		else if(lca==v){
    			//cout<<u<<' '<<v<<' '<<sum[u]<<' '<<siz[1]-siz[tag]<<' '<<outsum[tag]<<' '<<siz[u]<<' '<<dep[u]-dep[v]<<endl;
    			printf("%.7lf
    ", (double)(sum[u]*(siz[1]-siz[tag])+outsum[tag]*siz[u]) / ((siz[1]-siz[tag])*siz[u]) + dep[u]-dep[v]-1);
    		}
    		else{
    			//cout<<(double)sum[u]*siz[v]+(double)sum[v]*siz[u]/(siz[u]*siz[v])<<' '<<dep[u]<<' '<<dep[v]<<' '<<2*dep[lca]-1<<endl;
    			printf("%.7lf
    ", (double)(sum[u]*siz[v]+sum[v]*siz[u]) / (siz[u]*siz[v]) + dep[u]+dep[v]-2*dep[lca]-1);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Gitlab 11.0.3配置LDAP
    IntelliJ IDEA快速创建属性字段的get和set方法
    解决Maven引用POI的依赖,XSSFWorkbook依旧无法使用的问题
    解决方案看起来是受源代码管理,但无法找到它的绑定信息。保存解决方案的源代码管理设置的MSSCCPRJ.SCC文件或其他项可能己被删除。
    IntelliJ IDEA开发工具println报错的解决方法
    Eclipse开发工具printf打印方法提示报错的解决方法
    Java基础学习总结一(Java语言发展历史、JDK下载安装以及配置环境变量)
    浅谈JavaScript之function用括号包起来
    讲解JavaScript两个圆括号、自调用和闭包函数
    Visual Studio Code使用Open In Browser打开的是记事本
  • 原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/11509882.html
Copyright © 2020-2023  润新知