51nod1681 公共祖先

2021-08-20 11:53:12 字數 1487 閱讀 1162

1681 公共祖先

基準時間限制:1 秒 空間限制:131072 kb 分值: 80 

難度:5級演算法題

有乙個龐大的家族,共n人。已知這n個人的祖輩關係正好形成樹形結構(即父親向兒子連邊)。

在另乙個未知的平行宇宙,這n人的祖輩關係仍然是樹形結構,但他們相互之間的關係卻完全不同了,原來的祖先可能變成了後代,後代變成的同輩……

兩個人的親密度定義為在這兩個平行宇宙有多少人一直是他們的公共祖先。

整個家族的親密度定義為任意兩個人親密度的總和。

input

第一行乙個數n(1<=n<=100000)

接下來n-1行每行兩個數x,y表示在第乙個平行宇宙x是y的父親。

接下來n-1行每行兩個數x,y表示在第二個平行宇宙x是y的父親。

output

乙個數,表示整個家族的親密度。
input示例

5

1 33 5

5 44 2

1 21 3

3 41 5

output示例

6
﹡    lh

(題目提供者)

題解:可以把問題轉化一下,先計算出兩棵樹中的每個節點有多少個共同兒子,假設為x,那c(x, 2)就是該節點的貢獻。計算每個節點有多少個共同兒子可以利用dfs序加樹狀陣列維護。

**:

#includeusing namespace std;

int n,tot,rt,a[300001],next[300001],cnt,e[300001],head[300001],dfn[300001],low[300001];

long long ans,f[300001];

void build(int t,int k)

void dfs(int x,int la)

low[x]=cnt;

}int lowbit(int x)

void insert(int x,long long t)

long long query(int x)

void dfs1(int x,int la)

long long sum1=query(low[x])-query(dfn[x]-1);

ans+=(sum1-sum)*(sum1-sum-1)/2;

}int main()

for(i=1;i<=n;i++)

if(a[i]==0)

dfs(rt,0);

tot=0;

memset(head,0,sizeof(head));

memset(next,0,sizeof(next));

memset(a,0,sizeof(a));

for(i=1;i

for(i=1;i<=n;i++)

if(!a[i])

dfs1(rt,0);

printf("%lld",ans);

}

51nod 1681公共祖先

1681 公共祖先 有乙個龐大的家族,共n人。已知這n個人的祖輩關係正好形成樹形結構 即父親向兒子連邊 在另乙個未知的平行宇宙,這n人的祖輩關係仍然是樹形結構,但他們相互之間的關係卻完全不同了,原來的祖先可能變成了後代,後代變成的同輩 兩個人的親密度定義為在這兩個平行宇宙有多少人一直是他們的公共祖先...

公共祖先 51Nod 1681

給兩棵樹 問對於每對頂點 有多少除這兩個點之外的點 在這兩棵樹上都是這兩個點的公共祖先 考慮每個點的貢獻 對於乙個點 其子樹在兩棵樹上的有兩個dfs序 就看這兩個序列有多少數是相同的 c n,2 一下即可 至於查詢兩個序列的兩個區間有所少數是相同的 主席樹搞一下就行 這有個這型別的裸題 先把這個做明...

1681 公共祖先

有乙個龐大的家族,共n人。已知這n個人的祖輩關係正好形成樹形結構 即父親向兒子連邊 在另乙個未知的平行宇宙,這n人的祖輩關係仍然是樹形結構,但他們相互之間的關係卻完全不同了,原來的祖先可能變成了後代,後代變成的同輩 兩個人的親密度定義為在這兩個平行宇宙有多少人一直是他們的公共祖先。整個家族的親密度定...