《CF1120D Power Tree》

題目描述

給定一棵有?n?個頂點的有根樹,樹的根為頂點?1。每個頂點都有一個非負的價格。樹的葉子是指度為?1?且不是根的頂點。

Arkady 和 Vasily 在樹上玩一個奇怪的游戲。游戲分為三個階段。第一階段,Arkady 購買樹上的一些非空頂點集合。第二階段,Vasily 給所有葉子節點賦一些整數。第三階段,Arkady 可以進行若干次(也可以不進行)如下操作:選擇他在第一階段購買的某個頂點?v?和某個整數?x,然后將?x?加到?v?的子樹中所有葉子的整數上。整數?x?可以是正數、負數或零。

如果一條從葉子?a?到根的簡單路徑經過頂點?b,則稱葉子?a?在頂點?b?的子樹中。

Arkady 的目標是讓所有葉子上的整數都變為零。無論 Vasily 在第二階段如何賦值,Arkady 都要保證自己能夠達成目標。請你求出 Arkady 在第一階段至少需要支付的總費用?s,以及有多少個頂點屬于至少一個最優集合(即總費用為?s?的集合),使得 Arkady 購買這些頂點后能夠保證勝利。

請你輸出所有屬于至少一個最優集合的頂點編號。

輸入格式

第一行包含一個整數?n(2≤n≤200000),表示樹的頂點數。

第二行包含?n?個整數?c1?,c2?,…,cn?(0≤ci?≤109),其中?ci??表示第?i?個頂點的價格。

接下來的?n?1?行,每行包含兩個整數?a?和?b(1≤a,b≤n),表示樹上的一條邊。

輸出格式

第一行輸出兩個整數:Arkady 至少需要支付的最小總費用?s,以及屬于至少一個最優集合的頂點個數?k。

第二行輸出?k?個不同的整數,按升序排列,表示屬于至少一個最優集合的頂點編號。

顯示翻譯

題意翻譯

輸入輸出樣例

輸入 #1復制

5
5 1 3 2 1
1 2
2 3
2 4
1 5

輸出 #1復制

4 3
2 4 5 

輸入 #2復制

3
1 1 1
1 2
1 3

輸出 #2復制

2 3
1 2 3 

說明/提示

在第二個樣例中,所有包含兩個頂點的集合都是最優的。因此,每個頂點都至少屬于一個最優集合。

由 ChatGPT 4.1 翻譯

代碼實現:

#include <bits/stdc++.h>
using namespace std;

#define LONG_LONG long long
const int MAX_NODE = 2e5 + 5;

int node_count; ? ? ? ? ? ? ? ?// 節點總數
int degree[MAX_NODE]; ? ? ? ? ?// 每個節點的度數
int weight[MAX_NODE]; ? ? ? ? ?// 每個節點的權重
LONG_LONG dp[MAX_NODE][2]; ? ? // 動態規劃數組,dp[u][0/1]表示節點u的兩種狀態
vector<int> graph[MAX_NODE]; ? // 圖的鄰接表表示
vector<int> parent_choices[MAX_NODE][2]; ?// 記錄每個狀態下的父節點選擇

// 深度優先搜索,計算dp值
void dfs(int current_node, int parent_node) {
? ? // 如果是葉子節點(度數為1且有父節點)
? ? if (degree[current_node] == 1 && parent_node != 0) {
? ? ? ? dp[current_node][1] = weight[current_node]; ?// 選擇當前節點
? ? ? ? dp[current_node][0] = 0; ? ? ? ? ? ? ? ? ? ? // 不選擇當前節點
? ? ? ? return;
? ? }
? ??
? ? LONG_LONG sum = 0;
? ? // 計算所有子節點選擇狀態下的和
? ? for (int i = 0; i < graph[current_node].size(); ++i) {
? ? ? ? int child_node = graph[current_node][i];
? ? ? ? if (child_node != parent_node) {
? ? ? ? ? ? dfs(child_node, current_node);
? ? ? ? ? ? sum += dp[child_node][1];
? ? ? ? }
? ? }
? ??
? ? // 初始化當前節點的兩種狀態
? ? dp[current_node][1] = sum;
? ? dp[current_node][0] = sum;
? ??
? ? // 嘗試更新當前節點的兩種狀態
? ? for (int i = 0; i < graph[current_node].size(); ++i) {
? ? ? ? int child_node = graph[current_node][i];
? ? ? ? if (child_node != parent_node) {
? ? ? ? ? ? // 更新選擇當前節點的狀態
? ? ? ? ? ? dp[current_node][1] = min(dp[current_node][1], sum - dp[child_node][1] + dp[child_node][0] + weight[current_node]);
? ? ? ? ? ? // 更新不選擇當前節點的狀態
? ? ? ? ? ? dp[current_node][0] = min(dp[current_node][0], sum - dp[child_node][1] + dp[child_node][0]);
? ? ? ? }
? ? }
? ??
? ? // 記錄每個狀態下的父節點選擇
? ? for (int i = 0; i < graph[current_node].size(); ++i) {
? ? ? ? int child_node = graph[current_node][i];
? ? ? ? if (child_node != parent_node) {
? ? ? ? ? ? if (dp[current_node][1] == sum - dp[child_node][1] + dp[child_node][0] + weight[current_node]) {
? ? ? ? ? ? ? ? parent_choices[current_node][1].push_back(child_node);
? ? ? ? ? ? }
? ? ? ? ? ? if (dp[current_node][0] == sum - dp[child_node][1] + dp[child_node][0]) {
? ? ? ? ? ? ? ? parent_choices[current_node][0].push_back(child_node);
? ? ? ? ? ? }
? ? ? ? }
? ? }
}

bool selected[MAX_NODE]; ? ? ? // 標記節點是否被選中
bool visited[MAX_NODE][2]; ? ? // 標記節點的狀態是否已訪問

// 節點結構體,用于BFS
struct Node {
? ? int node; ? ? ? // 當前節點
? ? int parent; ? ? // 父節點
? ? int state; ? ? ?// 狀態(0或1)
};

queue<Node> q; ? ?// BFS隊列

// 廣度優先搜索,確定最終選擇的節點
void bfs() {
? ? q.push({1, 0, 1}); ?// 從根節點(1號節點)開始,狀態為1
? ??
? ? while (!q.empty()) {
? ? ? ? Node current = q.front();
? ? ? ? q.pop();
? ? ? ??
? ? ? ? int current_node = current.node;
? ? ? ? int parent_node = current.parent;
? ? ? ? int current_state = current.state;
? ? ? ??
? ? ? ? // 如果是葉子節點
? ? ? ? if (degree[current_node] == 1 && parent_node != 0) {
? ? ? ? ? ? if (current_state) {
? ? ? ? ? ? ? ? selected[current_node] = true;
? ? ? ? ? ? }
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ??
? ? ? ? // 重新計算子節點選擇狀態的和
? ? ? ? LONG_LONG sum = 0;
? ? ? ? for (int i = 0; i < graph[current_node].size(); ++i) {
? ? ? ? ? ? int child_node = graph[current_node][i];
? ? ? ? ? ? if (child_node != parent_node) {
? ? ? ? ? ? ? ? sum += dp[child_node][1];
? ? ? ? ? ? }
? ? ? ? }
? ? ? ??
? ? ? ? // 處理特殊情況
? ? ? ? if (sum == dp[current_node][current_state]) {
? ? ? ? ? ? for (int i = 0; i < graph[current_node].size(); ++i) {
? ? ? ? ? ? ? ? int child_node = graph[current_node][i];
? ? ? ? ? ? ? ? if (child_node != parent_node && !visited[child_node][1]) {
? ? ? ? ? ? ? ? ? ? visited[child_node][1] = true;
? ? ? ? ? ? ? ? ? ? q.push({child_node, current_node, 1});
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ??
? ? ? ? // 根據父節點選擇數量處理不同情況
? ? ? ? if (parent_choices[current_node][current_state].size() == 1) {
? ? ? ? ? ? // 只有一個選擇的情況
? ? ? ? ? ? if (current_state || weight[current_node] == 0) {
? ? ? ? ? ? ? ? selected[current_node] = true;
? ? ? ? ? ? }
? ? ? ? ? ??
? ? ? ? ? ? int chosen_child = parent_choices[current_node][current_state][0];
? ? ? ? ? ? for (int i = 0; i < graph[current_node].size(); ++i) {
? ? ? ? ? ? ? ? int child_node = graph[current_node][i];
? ? ? ? ? ? ? ? if (child_node != parent_node && child_node != chosen_child && !visited[child_node][1]) {
? ? ? ? ? ? ? ? ? ? visited[child_node][1] = true;
? ? ? ? ? ? ? ? ? ? q.push({child_node, current_node, 1});
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ??
? ? ? ? ? ? if (!visited[chosen_child][0]) {
? ? ? ? ? ? ? ? visited[chosen_child][0] = true;
? ? ? ? ? ? ? ? q.push({chosen_child, current_node, 0});
? ? ? ? ? ? }
? ? ? ? } else if (parent_choices[current_node][current_state].size() > 1) {
? ? ? ? ? ? // 多個選擇的情況
? ? ? ? ? ? if (current_state || weight[current_node] == 0) {
? ? ? ? ? ? ? ? selected[current_node] = true;
? ? ? ? ? ? }
? ? ? ? ? ??
? ? ? ? ? ? for (int i = 0; i < graph[current_node].size(); ++i) {
? ? ? ? ? ? ? ? int child_node = graph[current_node][i];
? ? ? ? ? ? ? ? if (child_node != parent_node && !visited[child_node][1]) {
? ? ? ? ? ? ? ? ? ? q.push({child_node, current_node, 1});
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ??
? ? ? ? ? ? for (int i = 0; i < parent_choices[current_node][current_state].size(); ++i) {
? ? ? ? ? ? ? ? int child_node = parent_choices[current_node][current_state][i];
? ? ? ? ? ? ? ? if (!visited[child_node][0]) {
? ? ? ? ? ? ? ? ? ? visited[child_node][0] = true;
? ? ? ? ? ? ? ? ? ? q.push({child_node, current_node, 0});
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
}

int main() {
? ? scanf("%d", &node_count);
? ??
? ? // 讀取節點權重
? ? for (int i = 1; i <= node_count; ++i) {
? ? ? ? scanf("%d", &weight[i]);
? ? }
? ??
? ? // 讀取邊信息,構建圖
? ? for (int i = 1; i < node_count; ++i) {
? ? ? ? int x, y;
? ? ? ? scanf("%d%d", &x, &y);
? ? ? ? graph[x].push_back(y);
? ? ? ? graph[y].push_back(x);
? ? ? ? degree[x]++;
? ? ? ? degree[y]++;
? ? }
? ??
? ? // 計算dp值
? ? dfs(1, 0);
? ??
? ? // 確定選擇的節點
? ? bfs();
? ??
? ? // 統計并輸出結果
? ? int selected_count = 0;
? ? for (int i = 1; i <= node_count; ++i) {
? ? ? ? if (selected[i]) {
? ? ? ? ? ? selected_count++;
? ? ? ? }
? ? }
? ??
? ? printf("%lld %d\n", dp[1][1], selected_count);
? ? for (int i = 1; i <= node_count; ++i) {
? ? ? ? if (selected[i]) {
? ? ? ? ? ? printf("%d ", i);
? ? ? ? }
? ? }
? ??
? ? return 0;
}
?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/94439.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/94439.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/94439.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CPTS-Agile (Werkzeug / Flask Debug)

枚舉 nmap -sC -sV -T4 -Pn -n -p- 10.10.11.203進行常規的網頁枚舉和測試發現報錯信息&#xff0c;‘Werkzeug / Flask Debug’ 測試Export導出功能發現存在路徑遍歷查看這篇文章 https://book.hacktricks.wiki/zh/network-services-pentesting/pentesting-web/werkzeug.html#…

【網絡運維】Shell 腳本編程:while 循環與 until 循環

Shell 腳本編程&#xff1a;while 循環與 until 循環 循環結構簡介 循環語句是 Shell 腳本中用于重復執行一條或一組指令的重要工具&#xff0c;直到滿足特定條件時停止執行。Shell 腳本中常見的循環語句包括 while、until、for 和 select。本文將重點介紹 while 和 until 兩種…

LLM 中評價指標與訓練概要介紹

在【LLM】LLM 中增量解碼與模型推理解讀一文中對 LLM 常見名詞進行了介紹&#xff0c;本文會對 LLM 中評價指標與訓練概要進行介紹&#xff0c;本文并未介紹訓練實操細節&#xff0c;未來有機會再了解&#xff5e; 一、LLM 如何停止輸出 在看 LLM 評價指標前&#xff0c;先看…

Java 20 新特性及具體應用

目錄 1. 模式匹配 for switch&#xff08;預覽特性&#xff09; 2. 記錄模式&#xff08;預覽特性&#xff09; 3. 外部函數與內存 API&#xff08;預覽特性&#xff09; 4. 矢量 API&#xff08;孵化器特性&#xff09; 5. 作用域值&#xff08;預覽特性&#xff09; 6. …

【STM32】CubeMX(十一):FreeRTOS任務掛起與解掛

這篇文章是 STM32 HAL FreeRTOS 下的任務掛起與恢復機制&#xff0c; 結合 CubeMX 圖示與代碼&#xff0c;構建了一個 FreeRTOS 控制示例。 本篇目標&#xff1a;創建兩個任務&#xff1a; 一個控制藍燈閃爍&#xff08;myTask01&#xff09; 另一個監控按鍵&#xff08;Start…

圖片預加載:提升Web性能的關鍵

&#x1f90d; 前端開發工程師、技術日更博主、已過CET6 &#x1f368; 阿珊和她的貓_CSDN博客專家、23年度博客之星前端領域TOP1 &#x1f560; 牛客高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》、《前端求職突破計劃》 &#x1f35a; 藍橋云課簽約作者、…

大模型壓縮三劍客:量化、剪枝與知識蒸餾全解析

在人工智能飛速發展的今天&#xff0c;大語言模型&#xff08;LLM&#xff09;如通義千問、GPT 等已成為推動智能應用的核心引擎。然而&#xff0c;這些模型動輒數十億甚至上千億參數&#xff0c;帶來了高昂的計算成本和部署門檻。如何在不顯著犧牲性能的前提下&#xff0c;讓大…

Seaborn數據可視化實戰:Seaborn基礎圖表繪制入門

基礎圖表繪制&#xff1a;Seaborn入門教程 學習目標 通過本課程的學習&#xff0c;你將掌握如何使用Seaborn庫繪制基礎圖表&#xff0c;包括條形圖、折線圖和散點圖。你將了解Seaborn的基本函數和參數設置&#xff0c;以及如何通過調整這些參數來優化圖表的視覺效果。 相關知識…

阿里開源通義萬相Wan2.2:視頻生成技術的革命性突破

在人工智能視頻生成領域,阿里云通義實驗室于2025年7月重磅開源了新一代視頻生成大模型 Wan2.2,其核心亮點包括人體動作生成的極致精度、電影級美學表達以及高效的資源利用效率,標志著視頻生成技術邁入了一個全新的階段。 一、核心功能:三大模型,覆蓋全場景視頻生成 Wan2.…

說說你對Integer緩存的理解?

大家好&#xff0c;我是鋒哥。今天分享關于【說說你對Integer緩存的理解?】面試題。希望對大家有幫助&#xff1b; 說說你對Integer緩存的理解? 超硬核AI學習資料&#xff0c;現在永久免費了&#xff01; Integer 緩存是 Java 中一個優化機制&#xff0c;它主要通過緩存一部…

高速CANFD收發器ASM1042在割草機器人輪轂電機通信系統中的適配性研究

摘要割草機器人輪轂電機的通信系統對其實現自主控制和高效作業至關重要。本文旨在研究國科安芯推出的高速CANFD收發器芯片ASM1042是否能夠滿足割草機器人輪轂電機通信系統的復雜需求。通過詳細分析輪轂電機通信系統的性能要求&#xff0c;以及ASM1042的電氣、功能和環境特性&am…

MTK Linux DRM分析(十二)- KMS Panel框架層(drm_panel.c、drm_mipi_dbi.c、drm_mipi_dsi.c)

一、簡介 三個代碼文件(drm_mipi_dbi.c、drm_panel.c、drm_mipi_dsi.c)的分析。這些文件都是Linux內核DRM(Direct Rendering Manager)子系統的組成部分,主要用于支持顯示面板,特別是通過MIPI(Mobile Industry Processor Interface)接口的顯示設備。它們提供了顯示驅動…

合合信息acge模型獲C-MTEB第一,文本向量化迎來新突破

前言&#xff1a; 在當今時代&#xff0c;大型語言模型以其驚人的發展速度和廣泛的應用前景&#xff0c;正成為全球科技界的矚目焦點。這些模型的強大能力&#xff0c;源自于背后默默支撐它們的Embedding技術——一種將語言轉化為機器可理解的數值向量的關鍵技術。隨著大型語言…

26.內置構造函數

2.內置構造函數2.1Object2.2Array2.3String2.4number

tauri配置允許執行eval腳本,在打包cocos游戲web/phone移動端的時候一定要配置

解決辦法&#xff1a;在tauriconfig中配置"csp": "default-src self asset: unsafe-inline customprotocol://* http://localhost:* ws:localhost:* unsafe-eval ipc: http://ipc.localhost; script-src unsafe-eval self https://www.googletagmanager.com uns…

K 均值聚類算法學習總結

一、聚類算法基礎認知 核心概念&#xff1a;聚類屬于無監督學習&#xff0c;核心是把 “相似的樣本” 自動分到同一組&#xff08;簇&#xff09;&#xff0c;不需要預先標注的標簽。主要挑戰是怎么定義 “相似性”、評估聚類效果以及確定最好的聚類數量。 距離度量&#xff1a…

基于Spring Cloud Gateway動態路由與灰度發布方案對比與實踐指導

基于Spring Cloud Gateway動態路由與灰度發布方案對比與實踐指導 一、問題背景介紹 在微服務架構中&#xff0c;API網關負責統一入口、路由分發與權限校驗功能。隨著業務需求的不斷演進&#xff0c;如何靈活地實現路由動態更新、版本灰度發布以及流量打點就成為運維和開發團隊的…

MySQL InnoDB Buffer Pool詳解:原理、配置與性能優化

1. 為什么需要 Buffer Pool&#xff1f;1.1 數據庫性能瓶頸分析在 MySQL 的運行過程中&#xff0c;最核心的性能瓶頸來自磁盤 IO。磁盤訪問延遲&#xff1a;一次機械硬盤 IO 操作可能需要數毫秒&#xff0c;即使是 SSD&#xff0c;訪問延遲也在幾十微秒量級。內存訪問延遲&…

ArcGIS Pro 安裝路徑避坑指南:從崩潰根源到規范實操(附問題修復方案)

作為 GIS 從業者&#xff0c;你是否遇到過這些糟心場景&#xff1a;ArcGIS Pro 雙擊啟動無響應、運行中突然彈出 “Runtime Error” 崩潰、加載矢量數據時提示 “找不到指定文件”&#xff1f;排查半天后發現&#xff0c;這些問題的 “元兇” 竟藏在安裝路徑里 —— 中文路徑或…

Python 實戰:內網滲透中的信息收集自動化腳本(2)

用途限制聲明&#xff0c;本文僅用于網絡安全技術研究、教育與知識分享。文中涉及的滲透測試方法與工具&#xff0c;嚴禁用于未經授權的網絡攻擊、數據竊取或任何違法活動。任何因不當使用本文內容導致的法律后果&#xff0c;作者及發布平臺不承擔任何責任。滲透測試涉及復雜技…