uva 1218
樹上的點可以涂成黑色或白色,求最少的黑色點,使得任意白點只和一個黑點相連
白點只和一個黑點相連,所以對于節(jié)點x, 不僅考慮 x ,son[x] 的情況,還有 x,father[x]?
// f[x][3]? ?黑點個數(shù)
第二維的意義:
0:?x 為?黑點
1:x為白點,且father[x] 為黑點
2:x 白點,father[x] 白點
f[x][0] = sum{ min(f[y][0],f[y][1] ) +1;? ?
f[x][1]=? sum{ f[y][2] }? ? ? ? ? ? ? ?// x為白點,且father[x] 為黑點
f[x][2] 需要枚舉一個子節(jié)點 W 作為黑點,然后其他的的點為白,但這樣做 復雜度O(n^2)?
這里就要注意利用已經(jīng)算出來的 f[x][1]??
? ? ? ? f[x][2]= min( f[x][1] - f[y][2] +f[y][0] }
#include <iostream> #include <vector> #include <cstring> using namespace std ; const int N=2e4;#define int long longvector<int>g[N];int n,f[N][3];void dp(int x,int fa){f[x][0]=1;for(int i=0;i<g[x].size();i++){int y=g[x][i]; if(y==fa) continue;dp(y,x);f[x][0]+=min(f[y][0],f[y][1]);f[x][1]+=f[y][2];}f[x][2]=1<<30;for(int i=0;i<g[x].size();i++){int y=g[x][i];f[x][2]=min(f[x][2],f[x][1]-f[y][2]+f[y][0]);}}signed main(){int i,x,y;while(cin>>n){memset(f,0,sizeof f);for(i=1;i<=n;i++) g[i].clear();for(i=1;i<n;i++) cin>>x>>y,g[x].push_back(y),g[y].push_back(x);;cin>>x;dp(1,0);cout<<min(f[1][0],f[1][2])<<'\n';if(x==-1) break;}}總結
- 上一篇: Android 状态栏工具类(实现沉浸式
- 下一篇: 卡题小结