樹形dp學習

2021-08-04 00:13:41 字數 3408 閱讀 4104

練習專題參考:傳送門

hdu 1520

題意:給出n個點,然後給出n個點對應的歡樂值,然後給出n-1條邊,a b,表示b是a的直屬上級,現在舉行乙個patry,但是要求員工和他的直屬上級不能同時來,問來的人的歡樂值的最大和是多少

思路:首先明確這是一棵有向樹,dp[i][0/1]代表第i個人來/不來的最大歡樂值。然後根據狀態轉移即可

#include using namespace std;

#define ll long long

#define pb push_back

#define mst(a, b) memset(a, b, sizeof a)

#define rep(i, x, n) for(int i = x; i <= n; ++i)

const int inf = 2e9;

const int qq = 6005;

int dp[qq][2];

vectorg[qq];

int deg[qq], rat[qq];

int n;

void dfs(int u)

dp[u][1] += rat[u];

return;

}int main()

int a, b;

while(scanf("%d%d", &a, &b) == 2)

mst(dp, 0);

for(int i = 1; i <= n; ++i)

} for(int i = 0; i < qq; ++i)

} return 0;

}

hdu 1561

最開始思路:利用拓撲來解, 但是。。。 wa

#include using namespace std;

#define ll long long

#define pb push_back

#define mk make_pair

#define mst(a, b) memset(a, b, sizeof a)

#define rep(i, x, n) for(int i = x; i <= n; ++i)

typedef pairpill;

const int qq = 200 + 10;

vectorg[qq];

int n, m, val[qq], deg[qq];

bool cmp(const pill &a, const pill &b)

int main()

int x;

rep(i, 1, n)

priority_queueq;

for(int i = 1; i <= n; ++i)

} int ans = 0;

while(!q.empty() && m--)

} printf("%d\n", ans);

} return 0;

}

可以試試這組資料

7 6

2 86 5

0 70 8

0 10

7 10

4 4ans:45

拓撲出來的結果是 44
正確思路:dp[i][j]代表以結點i為根的子樹上取包括結點i的j個時的最大價值,如何保證取得長度是鏈呢 ? 用dp的狀態來保證#include #include #include #include #include #include #include #include #include #include #include #include using namespace std;

#define ll long long

#define pb push_back

#define mk make_pair

#define pill pair#define mst(a, b) memset(a, b, sizeof a)

#define rep(i, x, n) for(int i = x; i <= n; ++i)

const int mod = 1e9 + 7;

const int qq = 250 + 10;

int n, m;

int dp[qq][qq], num[qq];

int mp[qq][qq], vis[qq];

void dfs(int u)

}} }

}int main()

m++;

for(int i = 0; i <= n; ++i)

} dfs(0);

printf("%d\n", dp[0][m]);

} return 0;

}

codeforces 219d

題意:n個結點,n-1條有向邊,如果邊是無向邊的話那麼從任意結點出發可以到達任意結點,現在問要選首都,要求首都能到達其他任意節點,問你最小要求改變幾條邊的方向,然後還要輸出首都的結點編號。

思路:首先以1為根結點進行dfs,求出以u為根結點到達其子樹時最小改變幾條邊的方向,然後再進行一次dfs這次維護以u個首都到達其他所有結點所需要改變邊方向數目

#include #include #include #include #include #include #include #include #include #include #include #include using namespace std;

#define ll long long

#define pb push_back

#define mk make_pair

#define pill pair#define mst(a, b) memset(a, b, sizeof a)

#define rep(i, x, n) for(int i = x; i <= n; ++i)

const int mod = 1e9 + 7;

const int qq = 2e5 + 10;

int n, s, t;

vectore[qq];

vectorf[qq];

int dp[qq], dir[qq];

void dfs(int u, int fa)

}void solve(int u, int fa)

}int main()

dfs(1, -1);

solve(1, -1);

int minx = 1e9;

for(int i = 1; i <= n; ++i)

printf("%d\n", minx);

for(int i = 1; i <= n; ++i)

} puts("");

return 0;

}

樹形dp學習

學習部落格 樹的性質 n個點,n 1條邊,任意兩個點之間只存在一條路徑,可以人為設定根節點,對於任意乙個節點只存在至多乙個父節點,其餘為子節點。記憶化樹形dp模型較為抽象難以理解,以下通過由淺到深的方式解析樹形dp以及樹的性質。樹形dp求樹的直徑 在一顆樹里找到點x,y,使得 xy 最大 如圖,我們...

樹形dp初次學習

1 什麼是樹型動態規劃 顧名思義,樹型動態規劃就是在 樹 的資料結構上的動態規劃,平時作的動態規劃都是線性的或者是建立在圖上的,線性的動態規劃有二種方向既向前和向後,相應的線性的動態規劃有二種方法既順推與逆推,而樹型動態規劃是建立在樹上的,所以也相應的有二個方向 1 葉 根 在回溯的時候從葉子節點往...

樹形DP學習總結

概述 樹形dp是dp的一種,有時候會和區間dp結合。由於樹有著天然的遞迴結構 父子結構 而且它作為一種特殊的圖 可以描述許多複雜的資訊 因此在樹就成了一種很適合dp的框架 問題 給你一棵樹 要求用最少的代價 最大的收益 完成給定的操作 樹形dp 一般來說都是從葉子從而推出根 當然 從根推葉子的情況也...