zoukankan      html  css  js  c++  java
  • [JZOJ 5814] 树

    题目:从u到v经过多少条边。
    思路:
    考虑他是怎么走的??
    \(u\)\(v\)一定是\(fa[u]\),\(fa[fa[u]]\),反正就是走\(LCA\),那么如果算出每个点到父亲的期望步数,和父亲到该点的期望步数就可做了。
    \(f(x) : x -> fa,g(x) : fa -> x\).

    那么:
    \(f(x) = {1 \over deg[x]} + \sum_{y是x的儿子} {{f(y) + 1 + f(x)} \over deg[x]}\)

    \(g(x) = {1 \over deg[fa[x]]} + {{1 + g[x] + g[fa[x]]} \over deg[fa[x]]} + \sum_{y 属于 son[fa[x]]{xor}y != x} {{g[x] + 1 + f[x]} \over {deg[fa[x]]}}\)
    于是我们罪恶的\(LCA\)开始了(情报中心)

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    inline int read () {
    	int q=0,f=1;char ch = getchar();
    	while(!isdigit(ch)){
    		if(ch=='-')f=-1;ch=getchar();
    	}
    	while(isdigit(ch)){
    		q=q*10+ch-'0';ch=getchar();
    	}
    	return q*f;
    }
    const int maxn = 1000010;
    ll dp[maxn][2];
    int head[maxn];
    int cnt;
    int siz[maxn];
    int f[maxn][20];
    int dep[maxn];
    int n,m,u,v,x,y;
    struct node {
    	int to;
    	int nxt;
    }e[maxn << 1];
    const int mod = 1e9+7;
    inline void add(int u,int v) {
    	e[++cnt].to = v;
    	e[cnt].nxt = head[u];
    	head[u] = cnt;
    	return;
    }
    inline void Add_edge(int u,int v) {
    	add(u,v);add(v,u);
    	return;
    }
    inline void dfs1(int x,int fa) {
    	siz[x] = 1;
    	for(int i = head[x];i;i=e[i].nxt) {
    		int y = e[i].to;
    		if(y != fa) {
    			dfs1(y,x);
    			siz[x] += siz[y];
    		}
    		dp[x][0] = siz[x] * 2 - 1;
    		dp[x][1] = (n - siz[x]) * 2 - 1;
    	}
    }
    inline void dfs2(int x,int fa) {
    	dep[x] = dep[fa] + 1;
    	dp[x][0] += dp[fa][0];
    	dp[x][1] += dp[fa][1];
    	f[x][0] = fa;
    	for(int i = 1;i <= 17; ++i) {
    		f[x][i] = f[f[x][i - 1]][i - 1];
    	}
    	for(int i = head[x];i;i=e[i].nxt) {
    		int y = e[i].to;
    		if(y != fa) dfs2(y,x);
    	}
    }
    inline int lca(int x,int y) {
    	if(dep[x] < dep[y]) swap(x,y);
    	for(int i = 17;i >= 0; --i) {
    		if(dep[x] - (1 << i) >= dep[y]) {
    			x = f[x][i];
    		}
    	}
    	if(x == y) return x;
    	for(int i = 17;i >= 0; --i) {
    		if(f[x][i] == f[y][i]) {
    			continue;
    		}
    		x = f[x][i];
    		y = f[y][i];
    	}
    	return f[x][0];
    }
    int main () {
    	freopen("tree.in","r",stdin);
    	freopen("tree.out","w",stdout);
    	n = read(),m = read();
    	for(int i = 1;i < n; ++i) {
    		u = read(),v = read();
    		Add_edge(u,v);
    	}
    	dfs1(1,0);
    	dp[1][0] = dp[1][1] = 0;
    	dfs2(1,0);
    	for(int i = 1;i <= m; ++i) {
    		x = read(),y = read();
    		int anc = lca(x,y);
    		printf("%d\n",(dp[x][0] + dp[y][1] - dp[anc][0] - dp[anc][1])%mod);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Vue路由配置
    vue项目 favicon.ico不显示解决方案
    Vux使用AjaxPlugin发送请求跨域问题解决
    改变vux样式,自定义样式
    Hive LLAP
    GitHub提交代码无contributions记录解决办法
    Java websocket+ nginx+redis负载均衡上实现单对单通讯
    springboot异步接口
    C#中$的用法(转载)
    vmware-tools灰色而无法安装的问题
  • 原文地址:https://www.cnblogs.com/akoasm/p/9579158.html
Copyright © 2011-2022 走看看