題幹在這裡:
本題老師教了我兩種方法,和大家分享一下,希望能幫到大家~~~
第一種思路:
由於每兩個點之間都有一些聯絡,我們可以先把兩兩之間的關係用邊的形式儲存下來:
head[x]是表示與x相連的第乙個元素的下標
edge[x].po是表示鏈頭為x
edge[x].next是表述鏈頭是x,與x相連的元素的下標
運作方法:每讀入乙個數k,就將head[x]轉變為k,之後再由edge陣列轉變下去,這樣就將k與整個鏈連線起來了
動態規劃總是要有狀態轉移方程的,我們用f[x]表示以x為根的最大價值數(其實就是題目中所謂的美麗指數,只不過這個名字太奇怪了。。。)。用g[x]表示以x為根,並且一定要取x的最大價值數
先考慮g[x]的狀態轉移方程:
考慮f[x]是否取x:
如果不取,那麼和他相連的子樹都可以取,狀態轉移方程是(其中y具體取值請參看本人的**):
當x是根的時候,需要用到它的子樹列,用深搜就可以實現。深搜有兩個引數:x表示處理的物件,fa表示該物件的父親(之後是不能再回到fa的!!)
最後獻上**~~~
#include
const
int maxn=20000;
const
int minvalue=-2147483647;
using
namespace
std;
struct node edge[2*maxn];
int head[maxn],n,a,b,value[maxn],tot,f[maxn],g[maxn];
void insert(int x,int y)
void readin()
for(int i=1;icin>>a>>b;
insert(a,b);
insert(b,a);
}} void dfs(int x,int fa)
t=edge[t].next;
}f[x]=max(f[x],g[x]);
} int main()
第二種思路:
儲存兩數關係方法與第一種思路一樣,連狀態轉移方程都一樣,就是求最大價值數的方法不同,上面了深搜的方法,將我們需要的狀態在需要的時候求出來。
這次的思路是:直接將所有的狀態都求出來,再從後往前改變每個父節點的最大價值數,這個可以用寬搜來實現。
最後附上我的**~~~
#include
#include
using
namespace
std;
const
int minvalue=-2147483647;
const
int maxn=200000;
struct nodetree[2*maxn];
int n,head[maxn],a,b,tot,qwq=1;
int value[maxn],f[maxn][2],g[maxn],k[maxn];
bool panduan[maxn];
void insert(int x,int y)
void readin()
for(int i=1;icin>>a>>b;
insert(a,b);
insert(b,a);
}}void bfs()
t=tree[t].next;
}st++;
}}void work()
}int main()
P1122 最大子樹和 (樹形DP)
第一次寫樹形dp,找了乙個簡單的題,先熟悉一下套路,雖然自己的這種寫法,過了,可以求到最大的子樹和,但是不能求到每個結點的最大子樹和,只有某一部分的最大子樹和的根,它是正確的,其他結點都是打工仔。遞迴下去,以子樹推當前結點和子樹的最優值,是可以辦到的 情況1 如果當前子樹 0,就不更新 情況2 如果...
P1122 最大子樹和
小明對數學飽有興趣,並且是個勤奮好學的學生,總是在課後留在教室向老師請教一些問題。一天他早晨騎車去上課,路上見到乙個老伯正在修剪花花草草,頓時想到了乙個有關修剪花卉的問題。於是當日課後,小明就向老師提出了這個問題 一株奇怪的花卉,上面共連有nn朵花,共有n 1n 1條枝幹將花兒連在一起,並且未修剪時...
P1122 最大子樹和 題解
同步 原題鏈結 簡要題意 給定一棵 n nn 個節點的樹,有點權,求其中最大的連通塊之和。資料範圍 n 1.6 1 04 n leq 1.6 times 10 4 n 1.6 104.很顯然,考慮用樹形 dp text dp 解決此題。f uf u fu 表示以 u uu 為根的子樹中包含 u uu...