HDU - 2196 Computer(树形dp)
題目鏈接:點(diǎn)擊查看
題目大意:給定n個(gè)點(diǎn)以及n-1條邊,保證可以組成一棵樹(shù),問(wèn)每個(gè)點(diǎn)所能到達(dá)的最遠(yuǎn)距離
題目分析:首先這是一顆無(wú)向圖所組成的樹(shù),經(jīng)過(guò)分析,我們可以得到任何一個(gè)點(diǎn),對(duì)于它所能到達(dá)的最遠(yuǎn)距離取決于兩個(gè)條件,一個(gè)是該點(diǎn)向下可以到達(dá)的最遠(yuǎn)距離,或者是該點(diǎn)向上可以到達(dá)的最遠(yuǎn)距離,求該點(diǎn)向下的距離好求,可以利用樹(shù)形dp的一般形式,回溯法,直接自底向上地往上求,不僅需要維護(hù)一個(gè)最大值,還需要維護(hù)一個(gè)次大值,接下來(lái)會(huì)用到,然后就是怎么求向上可以達(dá)到的距離了,我們可以在寫(xiě)一個(gè)dfs,剛才那個(gè)是自底向上維護(hù),那么新的dfs就變成自頂向下維護(hù)就好了,其實(shí)本質(zhì)上就是交換了一下轉(zhuǎn)移方程和遞歸入口的順序。
那么接下來(lái)在分析一下轉(zhuǎn)移方程該怎么寫(xiě),剛才我們提到了一共需要維護(hù)三個(gè)值,即向下的最大值,向下的次大值和向上的最大值,故我們需要用三個(gè)數(shù)組來(lái)維護(hù),我們就用dp[N][3]來(lái)維護(hù),第一維分別表示每個(gè)點(diǎn),第二維的0,1,2分別表示以上三個(gè)值。
關(guān)于最大值和次大值,只需要遵循
這樣就可以直接自底向上轉(zhuǎn)移了,還剩一個(gè)向上的最大值,這個(gè)我們?cè)撛趺聪肽?/p>
我先將轉(zhuǎn)移方程放上然后在來(lái)解釋:
dp[v][2]=max(dp[v][0]+w==dp[u][0]?dp[u][1]:dp[u][0],dp[u][2])+w;
其中v表示為u的兒子,w表示為u和v之間的權(quán)值
既然是自頂向下轉(zhuǎn)移,那么轉(zhuǎn)移的方向就是u->v來(lái)轉(zhuǎn)移,dp[u][2]可以當(dāng)做已知條件來(lái)用,我們可以直接用這個(gè)值加上u和v之間的權(quán)值w來(lái)更新dp[v][2],這樣確實(shí)是其中的一種情況,但卻不一定是最優(yōu)解,所以我們需要經(jīng)過(guò)比較選擇出最優(yōu)解來(lái)更新dp[v][2]才行,那么還有哪些途徑可以更新它呢?我們假設(shè)當(dāng)前的u為根節(jié)點(diǎn),那么既然v位于u的子樹(shù)中,我們需要判斷v是否位于u向下最大值的子樹(shù)中,如果是的話,那么經(jīng)過(guò)v點(diǎn)向上,我們可以經(jīng)過(guò)根節(jié)點(diǎn)u當(dāng)做中轉(zhuǎn)點(diǎn),到達(dá)u點(diǎn)的另一個(gè)次大值的子樹(shù)中,這樣可以保證了距離最大,如果v不在u的向下最大值的子樹(shù)中,那么必定可以經(jīng)過(guò)u到達(dá)最大值的子樹(shù)中,這樣通過(guò)比較這三種情況來(lái)確定了更新dp[v][2]的狀態(tài)。
最后輸出的結(jié)果便是從dp[i][0]和dp[i][2]中選擇較大的一個(gè)輸出了。
上代碼
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<map> #include<sstream> #include<cmath> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e4+100;struct Node {int to,w;Node(int TO,int W){to=TO;w=W;} };vector<Node>node[N];int dp[N][3];//0:向下最大值,1:向下次大值,2:向上最大值void dfs_down(int u,int fa) {int mmax=0;//最大值int mx=0;//次大值for(int i=0;i<node[u].size();i++){int v=node[u][i].to;int w=node[u][i].w;if(v==fa)continue;dfs_down(v,u);int temp=dp[v][0]+w;if(temp>=mmax){mx=mmax;mmax=temp;}else if(temp>mx){mx=temp;}}dp[u][0]=mmax;dp[u][1]=mx; }void dfs_up(int u,int fa) {for(int i=0;i<node[u].size();i++){int v=node[u][i].to;int w=node[u][i].w;if(v==fa)continue;dp[v][2]=max(dp[v][0]+w==dp[u][0]?dp[u][1]:dp[u][0],dp[u][2])+w;dfs_up(v,u);} }int main() { // freopen("input.txt","r",stdin);int n;while(scanf("%d",&n)!=EOF){for(int i=1;i<=n;i++)node[i].clear();for(int i=2;i<=n;i++){int w,u;scanf("%d%d",&u,&w);node[u].push_back(Node(i,w));node[i].push_back(Node(u,w));}memset(dp,0,sizeof(dp));dfs_down(1,-1);dfs_up(1,-1);for(int i=1;i<=n;i++)cout<<max(dp[i][0],dp[i][2])<<endl;}return 0; }?
?
總結(jié)
以上是生活随笔為你收集整理的HDU - 2196 Computer(树形dp)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: CodeForces - 1118F1
- 下一篇: POJ - 1655 Balancing