Test instructions: A tree, dyeing, each of the nodes that are not stained is connected to a dyed node, the number of nodes to find the least staining x (The following x represents the solution of the sub-problem)
Idea: A tree-shaped DP that refines the state so that each state of each node is recursive to each other
How to refine the state here is difficult, but also a common problem of this kind of problems
It is easy to know each node I at least two states: Dp[i][0]: I am not stained with the x of the subtree of I. DP[I][1]: I is stained with I for the X of the subtree
However, only these two states cannot implement state transitions because:
Dp[u][0]=sum (Dp[v][0],dp[v][1]) +1 (Dp[u][0] can find the state transition relationship, dp[u][0] and U's father okay )
But Dp[u][1] is not only related to U's son, but also to U's father, such as when his father dyed, U's son must not dye, when U's father did not dye, then you son must have a dyed color
So add a state to indicate the father's condition: dp[u][2], the father of U and U is not stained, dp[u][1] changed to u no stain but U's father dyed color
This recursive relationship can be written out.
So this kind of tree DP, to learn the appropriate state to add, how to refine the state
acceptedc++0.0162015-03-14 12:41:27#include<cstdio> #include <iostream> #include <cstring># Include<algorithm> #include <vector>using namespace std;const int n= 1e4+1e2;const int inf = 0x3f3f3f3f;int N, op;struct edge{int v; Edge (int _v=0): V (_v) {};}; int dep[n]; Depth of each node int fa[n]; Father node of each node int mdep;int dp[n][3]; Each node is a subtree of the root three states of each other recursive vector<edge> es[n];void dfs (int u,int pa) {fa[u]=pa; if (u==1) dep[u]=0; else dep[u]=dep[pa]+1; Mdep=max (Mdep,dep[u]); for (int i=0;i<es[u].size (); i++) {int v=es[u][i].v; if (V==PA) continue; DFS (V,U); }}void Ini () {for (int i=1;i<=n;i++) es[i].clear (); Mdep=-1; Memset (Dp,0,sizeof (DP));} void Debug () {printf ("mdep=%d\n", MDEP); printf ("\n0:"); for (int i=1;i<=n;i++) printf ("%11d", dp[i][0]); printf ("\n1:"); for (int i=1;i<=n;i++) printf ("%11d", dp[i][1]); printf ("\n2:"); for (int i=1;i<=n;i++) printf ("%11d", dp[i][2]); Puts ("");} int main () {while (scanf ("%d", &n), ~op) {ini (); int u,v; for (int i=1;i<n;i++) {scanf ("%d%d", &u,&v); Es[u].push_back (Edge (v)); Es[v].push_back (Edge (U)); } scanf ("%d", &op); DFS (1,0); for (int l=mdep;l>=0;l--) for (int u=1;u<=n;u++) if (dep[u]==l) { int sum1=0,sum2=0; int sz=es[u].size (); for (int j=0;j<sz;j++) {int v=es[u][j].v; if (V==fa[u]) continue; Sum1+=min (dp[v][0],dp[v][1]); if (Sum1>inf) Sum1=inf; Prevent explosion int sum2+=dp[v][2]; if (Sum2>inf) Sum2=inf; } dp[u][0]=sum1+1; dp[u][1]=sum2; for (int j=0;j<sz;j++) { int v=es[u][j].v; if (V==fa[u]) continue; else {dp[u][2]=inf; Dp[u][2]=min (Dp[u][2],dp[u][1]-dp[v][2]+dp[v][0]); }} if (Sz==1&&u!=1) Dp[u][2]=inf; A boundary of the leaf node, so to convict the root} printf ("%d\n", Min (dp[1][0],dp[1][2])); Debug (); } return 0;}
Uva1218perfect Service (staining problem--tree DP) (good problem, pass method)