poj 4045 Power Station(初涉樹形dp)

來源:互聯網
上載者:User

poj 4045 Power Station(初涉樹形dp)

http://poj.org/problem?id=4045


大致題意:有n個村莊,求將發電站建在哪一個村莊使得花費最少。這是一個無向無環圖。簡化一下就是求一個節點使它到其他所有節點的距離和最小。


起初一直在向最短路上靠,但因為節點和邊數太大,必定TLE。然後無比強大的嘯神隨便寫了兩個dfs就過掉了,簡直膜拜。賽後搜了搜題解,發現這是道樹形dp。sad,真的要好好刷dp了。

大體思路是將這個無向無環圖看做一個樹,我們就在這個樹上進行動態規劃。首先先隨便拿一個節點看做根節點(假設節點1),計算出它到其他點的最小距離和,那麼接下來當它的兒子做根節點的時候,根據父親節點的值以及他們的關係就可以直接計算齣兒子節點做根節點的距離和,具體是除該節點及其子樹之外的所有節點的距離都加1,而該節點及其子節點距離都減1。這個距離是隨便拿一個根節點dfs計算出來的。

設dp【】表示每個節點做根節點時它到子節點的距離之和,真正用到的是dp[1],son【】表示每個節點的孩子節點數目,包括自身。若已知父親節點的花費cost[pre],那麼當前節點u的花費cost[u] = cost[pre] + n-son[u] -son[u]。


總之,兩次dfs,第一次為了求得dp[1]和每個節點的孩子數目son[],第二次是有父親節點的花費求得當前節點的花費。

#include <stdio.h>#include <iostream>#include <map>#include <stack>#include <vector>#include <math.h>#include <string.h>#include <queue>#include <string>#include <stdlib.h>#include <algorithm>#define LL long long#define _LL __int64#define eps 1e-8#define PI acos(-1.0)using namespace std;const int maxn = 50000+10;struct node{int u,v,next;}edge[maxn*2];int cnt,head[maxn];int n,I,R;int son[maxn];//每個節點的兒子節點數目,這裡包含該節點本身方便計算。LL dp[maxn];//每個根節點的子節點到該節點的距離和LL cost[maxn];//以每個節點為根的花費void init(){cnt = 0;memset(head,-1,sizeof(head));}void add(int u, int v){edge[cnt] = (struct node){u,v,head[u]};head[u] = cnt++;}void dfs(int u, int pre){dp[u] = 0;son[u] = 1;for(int i = head[u]; i != -1; i = edge[i].next){int v = edge[i].v;if(v == pre) continue;dfs(v,u);son[u] += son[v]; //兒子數目dp[u] += dp[v] + son[v];//u到u的各個子節點的距離之和。}}void cal(int u, int pre){    if(u != 1)        cost[u] = cost[pre]+n-son[u]-son[u];    for(int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].v;        if(v == pre) continue;        cal(v,u);    }}int main(){int test;scanf("%d",&test);while(test--){scanf("%d %d %d",&n,&I,&R);int u,v;init();for(int i = 0; i < n-1; i++){scanf("%d %d",&u,&v);add(u,v);add(v,u);}//假設1為根節點dfs(1,0);        memset(cost, 0, sizeof(cost));        cost[1] = dp[1];        cal(1,0);        LL Min = cost[1];        for(LL i = 2; i <= n; i++)            Min = min(Min,cost[i]);        cout << Min*I*I*R << endl;        bool flag = false;        for(LL i = 1; i <= n; i++)        {            if(cost[i] == Min)            {                if(flag == false)                {                    flag = true;                    cout << i;                }                else cout << " " << i;            }        }        cout << endl << endl;}return 0;}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.