标签:子树 int 染色 p3177 HAOI2015 枚举 include 2010 define
分析
dp[x][i]表示以x为根的子树有i个黑点的方案数
我们发现每次转移要枚举这个点的子树大小和儿子的子树大小
看似复杂度O(n^3)
但是我们可以把循环转化为枚举x子树内的点再枚举它儿子的子树内的点
发现对于一个点它作为儿子子树的点枚举时最多只会和一个点同时枚举到一次
所以总共n^2组点
所以复杂度O(n^2)
代码
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cctype> #include<cmath> #include<cstdlib> #include<queue> #include<ctime> #include<vector> #include<set> #include<map> #include<stack> using namespace std; #define fi first #define se second #define mp make_pair #define pb push_back #define int long long vector<pair<int,int> >v[2010]; int dp[2010][2010],siz[2010],n,k; inline void dfs(int x,int fa){ siz[x]=1; for(int _=0;_<v[x].size();_++) if(v[x][_].fi!=fa){ int y=v[x][_].fi,z=v[x][_].se; dfs(y,x); siz[x]+=siz[y]; } memset(dp[x],-1,sizeof(dp[x])); dp[x][0]=dp[x][1]=0; for(int _=0;_<v[x].size();_++) if(v[x][_].fi!=fa){ int y=v[x][_].fi,z=v[x][_].se; for(int i=min(siz[x],k);i>=0;i--) for(int j=0;j<=min(siz[y],i);j++){ if(dp[x][i-j]==-1)continue; int res=j*(k-j)*z+(siz[y]-j)*(n-k-siz[y]+j)*z; dp[x][i]=max(dp[x][i],dp[x][i-j]+dp[y][j]+res); } } return; } signed main(){ int i,j; scanf("%lld%lld",&n,&k); for(i=1;i<n;i++){ int x,y,z; scanf("%lld%lld%lld",&x,&y,&z); v[x].pb(mp(y,z)); v[y].pb(mp(x,z)); } dfs(1,0); printf("%lld\n",dp[1][k]); return 0; }
标签:子树,int,染色,p3177,HAOI2015,枚举,include,2010,define 来源: https://www.cnblogs.com/yzxverygood/p/11519110.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。