問題描述
有一棵 n 個節點的樹,樹上每個節點都有乙個正整數權值。如果乙個點被選擇了,那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?
輸入格式
第一行包含乙個整數 n 。
接下來的一行包含 n 個正整數,第 i 個正整數代表點 i 的權值。
接下來一共 n-1 行,每行描述樹上的一條邊。
輸出格式
輸出乙個整數,代表選出的點的權值和的最大值。
樣例輸入
51 2 3 4 5
1 2
1 3
2 4
2 5
樣例輸出
12樣例說明
選擇3、4、5號點,權值和為 3+4+5 = 12 。
資料規模與約定
對於20%的資料, n <= 20。
對於50%的資料, n <= 1000。
對於100%的資料, n <= 100000。
權值均為不超過1000的正整數。
思路:用f[i]表示從子樹i中選擇結點,且結點i必須被選擇的最大值,用g[i]表示從子樹i中選擇結點,且結點i必須不被選擇的最大值。
則f[i]=pow[i]+\sum(g[j]),其中pow[i]表示結點i的權值,j是i的子結點,\sum(g[j])表示所有g[j]的和。
g[i]=\sum(max(f[j], g[j])),其中j是i的子結點。
最後輸出f[p],g[p]中較大的數即為答案,p為樹的根節點,這道題裡任何一點都可以視為根節點。
#include #includeusing namespace std;
const int e=100100;
int f[e],g[e],visited[e];
int pow[e];
struct child
;//用鄰接表儲存
child *a[e];//a[i]鍊錶記錄了i結點的所有相鄰結點
void tree(int u,int v)
void dfs(int v)//執行dfs(i)會得到f[i]和g[i]的值
} f[v]+=pow[v-1];//記得加上pow的值
}int main()
//輸入
memset(a,null,sizeof(a));
memset(visited,0,sizeof(visited));
memset(f,0,sizeof(f));
memset(g,0,sizeof(g)); //初始化
for(int i=0;i>u>>v;
tree(u,v);//記錄u,v結點的資訊
} dfs(1);//可以將結點1視為根節點,然後深搜
cout<}
藍橋杯 演算法訓練 ALGO 4 結點選擇
本人是乙個剛剛接觸c 不久的傻學生 記錄一些自己的學習過程。大神路過可以批評指正 問題描述 有一棵 n 個節點的樹,樹上每個節點都有乙個正整數權值。如果乙個點被選擇了,那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?輸入格式 第一行包含乙個整數 n 接下來的一行包含 n 個正整數,...
藍橋杯 ALGO 4 結點選擇
演算法訓練 結點選擇 時間限制 1.0s 記憶體限制 256.0mb 問題描述 有一棵 n 個節點的樹,樹上每個節點都有乙個正整數權值。如果乙個點被選擇了,那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?輸入格式 第一行包含乙個整數 n 接下來的一行包含 n 個正整數,第 i 個正...
藍橋杯ALGO 4演算法訓練 結點選擇(樹形DP)
問題描述 有一棵 n 個節點的樹,樹上每個節點都有乙個正整數權值。如果乙個點被選擇了,那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?輸入格式 第一行包含乙個整數 n 接下來的一行包含 n 個正整數,第 i 個正整數代表點 i 的權值。接下來一共 n 1 行,每行描述樹上的一條邊。...