題意:求樹的最小支配集。
思路:動態規劃。一開始每個點只取了兩個變數,表示在以其為根的子樹中選擇和不選擇該點的最少點數。由一組資料(6個點的路徑)發現了問題,考慮第3個點的時候,如果不選擇此點,那麼第4個點必須要選取,實際上這是不必的。該組資料的最優解是選擇第2和第5個點。
dp1[x]表示選擇第x個點。
dp0[x][0]表示不選擇第x個點,而且該點並沒有被兒子所覆蓋。
dp0[x][1]表示不選擇第x個點,但是該點已經被兒子所覆蓋了,即至少有乙個兒子被選擇。
如此一來就對了,轉移方程見**,懶得寫了。
#include #include #include #include #include #include using namespace std;
#define clc(s,t) memset(s,t,sizeof(s))
#define inf 0x3fffffff
#define n 10005
struct edgee[n<<1];
int first[n],n,top;
int dp1[n],dp0[n][2];
void add(int x,int y)
void dfs(int x,int fa)
}dp1[x] ++;
if(son)
dp0[x][1] = 1;
}int main(){
int i,a,b;
clc(first,-1);
clc(dp1, 0);
clc(dp0, 0);
top = 0;
scanf("%d",&n);
for(i = 1;i
每日一題 POJ 2486 樹形dp 樹上揹包
並不難寫,關鍵是要想清楚。樹形dp的第乙個比較完整寫完的題,是比較經典的題,來紀念一下。一開始沒想清楚是因為對揹包問題的滾動陣列優化的理解不夠,自然在樹上的問題也沒思考清楚。同時因為每個case過後忘記清零,導致re了一發,以後需要注意。dpr是回到該點,nr是不回到該點,轉移方程如 ac 耗時18...
POJ 1655 樹的重心(樹形 DP)
balancing act 定義乙個點的 平衡 值等於將這個點拆去後,形成的子樹中節點數的最大值。求一棵樹 平衡 值最小的點。這其實就是樹的重心的概念,通過樹形 dp 很容易解決。當去掉抹一點後,它下面的子樹的節點個數通過 dfs 可以得到,它上面的子樹的節點個數等於總節點個數減去它本身及其子節點的...
poj1655 樹的重心 樹形dp
樹的重心定義為 找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵樹的重心,刪去重心後,生成的多棵樹盡可能平衡.處理處每個節點的孩子有幾個,和樹的大小就好了。include include include include include define inf 99999999 usi...