51nod 1681公共祖先

xiaoxiao2021-02-28  33

1681 公共祖先 有一个庞大的家族,共n人。已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边)。 在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完全不同了,原来的祖先可能变成了后代,后代变成的同辈…… 两个人的亲密度定义为在这两个平行宇宙有多少人一直是他们的公共祖先。 整个家族的亲密度定义为任意两个人亲密度的总和。 Input 第一行一个数n(1<=n<=100000) 接下来n-1行每行两个数x,y表示在第一个平行宇宙x是y的父亲。 接下来n-1行每行两个数x,y表示在第二个平行宇宙x是y的父亲。 Output 一个数,表示整个家族的亲密度。 Input示例 5 1 3 3 5 5 4 4 2 1 2 1 3 3 4 1 5 Output示例 6 ﹡ LH (题目提供者)

dfs+ u dfs1dfs dfs2uu

#include<iostream> #include<cstdio> using namespace std; #define N 100010 #define ll long long #define lowbit(x) ((x)&(-x)) int n; struct node{ int l,r; }stack[N]; int vet[N],Next[N],hed[N],h[N],in[N]; ll ans; int num,cnT; void add(int x){ for (int i=x;i<=N-10;i+=lowbit(i)) h[i]+=1; } int get(int x){ int ans=0; for (int i=x;i>0;i-=lowbit(i)) ans+=h[i]; return ans; } void edgeadd(int u,int v){ ++num; vet[num]=v; Next[num]=hed[u]; hed[u]=num; } void dfs1(int u,int fa){ stack[u].l=++cnT; for (int i=hed[u];i!=-1;i=Next[i]){ int v=vet[i]; if (v==fa) continue; dfs1(v,u); } stack[u].r=cnT; } void dfs2(int u,int fa){ add(stack[u].l); int nowl=get(stack[u].r)-get(stack[u].l-1); for (int i=hed[u];i!=-1;i=Next[i]){ int v=vet[i]; if (v==fa) continue; dfs2(v,u); } int nowr=get(stack[u].r)-get(stack[u].l-1); ans+=(ll)(nowr-nowl)*(nowr-nowl-1)/2; } void read(int ha){ num=0; for (int i=1;i<=n;++i) hed[i]=-1,in[i]=0; for (int i=1;i<n;++i){ int x,y; scanf("%d%d",&x,&y); edgeadd(x,y); ++in[y]; } int root=0; for (int i=1;i<=n;++i) if (in[i]==0){ root=i; break; } if (!ha) dfs1(root,0); else dfs2(root,0); } int main(){ scanf("%d",&n); ans=0; read(0); read(1); printf("%lld\n",ans); return 0; }
转载请注明原文地址: https://www.6miu.com/read-1699972.html

最新回复(0)