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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

51Nod 1322 - 关于树的函数(树DP)

發布時間:2024/9/5 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 51Nod 1322 - 关于树的函数(树DP) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【題目描述】

【思路】
看了大佬的題解才想明白的,f_zyj大佬的題解
兩棵樹,對第一棵樹暴力枚舉所有邊,拆掉這條邊后的兩個子樹對應兩個集合 A1,B1A1,B1A1,B1,用 dfsdfsdfs 枚舉,然后在枚舉出某一個 A1,A2A1,A2A1,A2 時,所有在 A1A1A1 中的節點 uuuused[u]=trueused[u]=trueused[u]=true,現在對第二棵樹枚舉,dfs2dfs2dfs2 枚舉的時候和剛才 dfs1dfs1dfs1 不同,這回是把節點 uuuuuu 的所有子孫看成集合 B1B1B1,樹上的其它節點看成是集合 B2B2B2,這樣一來,可以遞推的計算集合中元素的個數已經 A1,B1A1,B1A1,B1 交集的大小,設第二棵樹上節點 uuu 對應的集合大小為 num[u]num[u]num[u],和 A1A1A1 的交集大小為 dp[u]dp[u]dp[u],如果 uuu 的所有兒子節點所在集合為 SSS ,那么就有 num[u]=1+∑v∈Snum[v]num[u]=1+\sum_{v \in S}num[v]num[u]=1+vS?num[v] dp[u]={1+∑v∈Sdp[v]???(used[u]=true)???????∑v∈Sdp[v]???(used[u]=false) dp[u]=\begin{cases} 1+\sum_{v \in S}dp[v] \ \ \ (used[u]=true) \\ \ \ \ \ \ \ \ \sum_{v \in S}dp[v] \ \ \ (used[u]=false) \end{cases} dp[u]={1+vS?dp[v]???(used[u]=true)???????vS?dp[v]???(used[u]=false)?
而且只要知道 A1,B1A1,B1A1,B1 的交集大小,并且 A1,A2A1,A2A1A2交集為空,B1,B2B1,B2B1,B2交集為空,因此其余三對集合的交集大小也能推算出來,取一下最大值,不過題解里的“樹歸”是個啥?樹上遞歸嗎?不是很懂…

#include<bits/stdc++.h> #define max(a,b)(a>b?a:b) using namespace std; const int maxn=4005;struct Edge{int from,to;Edge(int f=0,int t=0):from(f),to(t){} };int n,a1; long long ans; bool used[maxn]; int num[maxn],dp[maxn]; vector<int> g1[maxn],g2[maxn]; Edge edges[maxn];void dfs1(int u,int fa){used[u]=true;++a1;for(int i=0;i<g1[u].size();++i){int v=g1[u][i];if(v!=fa && !used[v]) dfs1(v,u);} }void dfs2(int u,int fa){num[u]=1;dp[u]=used[u]?1:0;for(int i=0;i<g2[u].size();++i){int v=g2[u][i];if(v!=fa){dfs2(v,u);num[u]+=num[v];dp[u]+=dp[v];}}if(u!=0){//u=0時樹沒有被分成兩部分所以不算 int b1=num[u];//集合a1和b1的交集大小為dp[u]int maxv=0;maxv=max(maxv,dp[u]);maxv=max(maxv,a1-dp[u]);maxv=max(maxv,b1-dp[u]);maxv=max(maxv,n-a1-b1+dp[u]);ans+=(long long)maxv*maxv;} }int main(){scanf("%d",&n);for(int i=0;i<n-1;++i){int u,v;scanf("%d%d",&u,&v);g1[u].push_back(v);g1[v].push_back(u);edges[i]=Edge(u,v);}for(int i=0;i<n-1;++i){int u,v;scanf("%d%d",&u,&v);g2[u].push_back(v);g2[v].push_back(u);}for(int i=0;i<n-1;++i){a1=0;memset(used,0,sizeof(used));dfs1(edges[i].from,edges[i].to);dfs2(0,-1);}printf("%lld\n",ans);return 0; }

轉載于:https://www.cnblogs.com/wafish/p/10465115.html

總結

以上是生活随笔為你收集整理的51Nod 1322 - 关于树的函数(树DP)的全部內容,希望文章能夠幫你解決所遇到的問題。

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