日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【dfs】树上游戏(P2664)

發布時間:2023/12/3 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【dfs】树上游戏(P2664) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

P2664


題目大意

定義s(i,j)為i到j路徑上的顏色數量,sumi=∑j=1ns(i,j)sum_i=\sum_{j=1}^ns(i,j)sumi?=j=1n?s(i,j)

現在讓你求sum的和


解題思路

考慮一種顏色的貢獻:

先把該顏色的點刪掉,這樣就形成了若干小樹

不難發現,同一小樹中的點對不會產生貢獻,而不同小樹的點對會產生一點貢獻

那么在計算一個點的貢獻時,就是n-所在小樹的size

那么直接dfs遍歷每一個點,然后計算

因為一個點只會影響當前顏色的貢獻,所以時間是O(n)的


code

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 100010 using namespace std; ll n,x,y,now,tot,sum,f[N],p[N],h[N],c[N],sz[N],num[N],ans[N]; struct rec {ll to,nx; }e[N<<1]; void add(ll x,ll y) {e[++tot].to=y;e[tot].nx=h[x];h[x]=tot;return; } void dfs1(ll x,ll fa) {ll g=num[c[fa]];num[c[x]]++;sz[x]=1;for(ll i=h[x];i;i=e[i].nx){ll y=e[i].to;if(y==fa)continue;dfs1(y,x);sz[x]+=sz[y];}if(fa)num[c[fa]]+=(f[x]=sz[x]-(num[c[fa]]-g));//計算小樹大小return; } void dfs2(ll x,ll fa) {ll g=num[c[fa]];now+=f[x]-num[c[fa]];//減去上一小樹大小num[c[fa]]=f[x];ans[x]=sum*n-now+num[c[x]];//當前結點顏色能不減for(ll i=h[x];i;i=e[i].nx){ll y=e[i].to;if(y==fa)continue;dfs2(y,x);}num[c[fa]]=g;now-=f[x]-num[c[fa]];return; } int main() {scanf("%lld",&n);for(ll i=1;i<=n;++i){scanf("%lld",&c[i]);if(!p[c[i]])p[c[i]]=1,sum++;}for(ll i=1;i<n;++i){scanf("%lld%lld",&x,&y);add(x,y);add(y,x);}dfs1(1,0);num[0]=0;for(ll i=1;i<=100000;++i){if(!p[i])continue;num[i]=n-num[i];now+=num[i];}dfs2(1,0);for(ll i=1;i<=n;++i)printf("%lld\n",ans[i]);return 0; }

總結

以上是生活随笔為你收集整理的【dfs】树上游戏(P2664)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。