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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

2018.09.01 独立集(树形dp)

發布時間:2025/3/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2018.09.01 独立集(树形dp) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

描述

給定一顆樹(邊權為1),選取一個節點子集,使得該集合中任意兩個節點之間的距離都大于K。求這個集合節點最多是多少

輸入

第一行是兩個整數N,K
接下來是N-1行,每行2個整數x,y,表示x與y有一條邊

輸出

1個整數表示最多的節點數

樣例輸入

3 1
1 2
1 3

樣例輸出

2

提示

測試點N的上限K特征
1151
210001
310001
41000001
51000001
6152
710002
810002
91000002
101000002

樹形dp入門題。
T=2的情況有點意思。
設當前訪問第i個節點。
f[i][0]f[i][0]:i不選但i父親選。
f[i][1]f[i][1]:不選且i父親不選。
f[i][2]f[i][2]:i選。
顯然有:
f[i][2]=1+vf[v][0]f[i][2]=1+∑vf[v][0]
以及:
f[i][0]=vf[v][1]f[i][0]=∑vf[v][1]
關鍵是f[i][1]f[i][1]
這個東西需要考慮兒子之間是否沖突,因此最優值的產生有兩種可能:
1. 所有兒子都不選。
2. 某一個兒子選,其余不選。

因此有f[i][1]=(vf[v][1])+max(0,f[v][2]?f[v][1])f[i][1]=(∑vf[v][1])+max(0,f[v][2]?f[v][1])
代碼:

#include<bits/stdc++.h> #define N 100005 using namespace std; inline int read(){int ans=0;char ch=getchar();while(!isdigit(ch))ch=getchar();while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();return ans; } int first[N],n,k,cnt=0,f[N][3]; struct edge{int v,next;}e[N<<1]; inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;} inline int max(int a,int b){return a>b?a:b;} inline int dfs1(int p,bool k,int fa){if(f[p][k]!=-1)return f[p][k];f[p][k]=k;for(int i=first[p];i;i=e[i].next){int v=e[i].v;if(v==fa)continue;if(!k)f[p][k]+=max(dfs1(v,0,p),dfs1(v,1,p));else f[p][k]+=dfs1(v,0,p);}return f[p][k]; } inline int dfs2(int p,int k,int fa){if(f[p][k]!=-1)return f[p][k];f[p][k]=(k==2);if(!k){for(int i=first[p];i;i=e[i].next){int v=e[i].v;if(v==fa)continue;f[p][k]+=dfs2(v,1,p);}}else if(k==1){int max1=0;for(int i=first[p];i;i=e[i].next){int v=e[i].v;if(v==fa)continue;f[p][k]+=dfs2(v,1,p);int tmp=dfs2(v,2,p)-dfs2(v,1,p);if(max1<tmp)max1=tmp;}f[p][k]+=max1;}else for(int i=first[p];i;i=e[i].next){int v=e[i].v;if(v==fa)continue;f[p][k]+=dfs2(v,0,p);}return f[p][k]; } int main(){n=read(),k=read();for(int i=1;i<n;++i){int u=read(),v=read();add(u,v),add(v,u);}memset(f,-1,sizeof(f));if(k==1)cout<<max(dfs1(1,1,1),dfs1(1,0,1));else cout<<max(dfs2(1,1,1),dfs2(1,2,1));return 0; }

轉載于:https://www.cnblogs.com/ldxcaicai/p/9738324.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的2018.09.01 独立集(树形dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

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