BZOJ 4813: [Cqoi2017]小Q的棋盘
Description
一棵\(n\)个节点的树,从根节点走\(k\)步,最多经过多少节点.\(n,k\leqslant 100\)
Solution
树形DP.
\(f[i][j][0/1]\)表示从节点\(i\),向下走\(j\)步,是否回来,经过最多的节点数.
Code
/************************************************************** Problem: 4813 User: BeiYu Language: C++ Result: Accepted Time:28 ms Memory:1380 kb ****************************************************************/ #include <bits/stdc++.h> using namespace std; #define uor(i,j,k) for(int i=j;i<=(int)k;i++) #define uep(i,j,k) for(int i=j;i<(int)k;i++) #define dor(i,j,k) for(int i=j;i>=(int)k;i--) const int N = 105; int n,m; vector<int> g[N]; int f[N][N][2]; void AddEdge(int u,int v) { g[u].push_back(v),g[v].push_back(u); } void DFS(int u,int fa) { uep(t,0,g[u].size()) { int v=g[u][t]; if(v==fa) continue; DFS(v,u); dor(i,m,1) uor(j,0,i) { if(j-1>=0) f[u][i][0]=max(f[u][i][0],f[u][i-j][1]+f[v][j-1][0]); if(j-2>=0) f[u][i][1]=max(f[u][i][1],f[u][i-j][1]+f[v][j-2][1]), f[u][i][0]=max(f[u][i][0],f[v][j-2][1]+f[u][i-j][0]); } } uor(i,0,m) f[u][i][0]=max(f[u][i][0]+1,f[u][i-1][0]), f[u][i][1]=max(f[u][i][1]+1,f[u][i-1][1]); // cout<<"---------"<<endl; // cout<<u<<"-->"<<endl; // uor(i,0,m) cout<<f[u][i][0]<<" ";cout<<endl; // uor(i,0,m) cout<<f[u][i][1]<<" ";cout<<endl; } int main() { scanf("%d%d",&n,&m); int u,v; uep(i,1,n) scanf("%d%d",&u,&v),AddEdge(u,v); DFS(0,0); printf("%d\n",f[0][m][0]); return 0; }