zoukankan      html  css  js  c++  java
  • 【GOJ 3007】树

    题目

    正解

    两条树链的交显然也是一条链。链有一个很好的性质:链上的点数(-)链上的边数(=1)。所以如果一对链在同一个点上出现,答案(+1);在同一条边上出现则答案(-1),这样就可以得到最终的答案。在求出一条链的(lca)后,可以树上差分快速求出每个点、每条边被多少条链覆盖,进而求出最终答案。

    代码

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    const LL N=1e5+2;
    struct edge {
    	LL to,nxt,w;
    } e[N*5];
    LL n,m,head[N],cnt;
    void add(LL u,LL v) {
    	e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt;
    }
    LL dep[N],f[N][25];
    void build(LL u,LL fa) {
    	dep[u]=dep[fa]+1;
    	for(LL i=1; (1<<i)<=dep[u]; i++) {
    		f[u][i]=f[f[u][i-1]][i-1];
    	}
    	for(LL i=head[u]; i; i=e[i].nxt) {
    		LL v=e[i].to;
    		if(fa==v) {
    			continue;
    		}
    		f[v][0]=u,build(v,u);
    	}
    }
    LL lca(LL x,LL y) {
    	if(dep[x]<dep[y]) {
    		swap(x,y);
    	}
    	for(LL i=22; i>=0; i--) {
    		if(dep[f[x][i]]>=dep[y]) {
    			x=f[x][i];
    		}
    		if(x==y) {
    			return x;
    		}
    	}
    	for(LL i=22; i>=0; i--) {
    		if(f[x][i]^f[y][i]) {
    			x=f[x][i],y=f[y][i];
    		}
    	}
    	return f[x][0];
    }
    struct lian {
    	LL u,v,hrq;
    } lsc[N];
    LL sum[N];
    void dfs(LL u,LL fa) {
    	for(LL i=head[u]; i; i=e[i].nxt) {
    		LL v=e[i].to;
    		if(v==fa) {
    			continue;
    		}
    		sum[v]+=sum[u];
    		dfs(v,u);
    	}
    }
    int main() {
    	scanf("%lld %lld",&n,&m);
    	for(LL i=1,u,v; i<n; i++) {
    		scanf("%lld %lld",&u,&v),add(u,v),add(v,u);
    	}
    	build(1,0);
    	for(LL i=1; i<=m; i++) {
    		scanf("%lld %lld",&lsc[i].u,&lsc[i].v);
    		if(lsc[i].u>lsc[i].v) {
    			swap(lsc[i].u,lsc[i].v);
    		}
    		lsc[i].hrq=lca(lsc[i].u,lsc[i].v),sum[lsc[i].hrq]++;
    	}
    	LL ans=0;
    	for(LL i=1; i<=n; i++) {
    		ans+=sum[i]*(sum[i]-1)/2;
    	}
    	dfs(1,0);
    //	//Debug begin
    //	for(LL i=1; i<=n; i++) {
    //		printf("%lld ",sum[i]);
    //	}
    //	//Debug end
    	for(LL i=1; i<=m; i++) {
    		ans+=sum[lsc[i].u]+sum[lsc[i].v]-2*sum[lsc[i].hrq];
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    rsync的man手册(未完成)
    rsync基础
    命令:mktemp
    命令:install
    [Abp vNext 源码分析]
    异常吞噬问题一则
    使用 Polly 实现复杂策略(超时重试)
    在 DotNetty 中实现同步请求
    使用 C# 实现 CJ-T188 水表协议和 DL-T645 电表协议的解析与编码
    DevExpress 使用 GridControl 时,数据源无法立即更新的问题
  • 原文地址:https://www.cnblogs.com/Sam2007/p/13387645.html
Copyright © 2011-2022 走看看