问题描述

给定一棵树 T,树中每个顶点 u 都有一个权 w(u),权可以是负数。现在要找到树 T 的一个连通子图使该子图的权之和最大。

对于给定的树 T,编程计算树 T 的最大连通分支。

数据输入

第一行有1个正整数n,表示树T有n个顶点,顶点的编号为1~n

第二行有n个整数,表示顶点的权值

接下来n-1行,每行有两个整数u、v,表示顶点u与v相连

结果输出

一个整数,表示最大连通分支的权值

输入输出样例

Input                           Output6                               4
-1 1 3 1 -3 2
4 1
1 3
1 2
4 5
6 5

算法分析(一)

顶层问题:如何确定哪些顶点存在于最大连通子图中?

分解问题:如何求有顶点4存在的最大连通分支?

再次分解:考虑顶点4的两棵子树

算法分析(二)

最大连通分支在子树或树中,因此对树进行遍历,依次求出以每个结点为树根的最大连通分支权值

两个性质:最优子结构性质、子问题重叠性质

动态规划!!

    

算法步骤

对于叶子结点:最大连通分支的权值为该点的权值

某一结点的最大连通权值>0,则将其值加到它的父亲结点的最大连通权值,反之舍弃该值

最终求出根结点的最大连通权值,结束遍历

所求最大连通分支的权值,即为结点中最大连通权值的最大值

C++代码实现

#include <iostream>
#include <vector>
#include <list>
#include <queue>
#include <chrono>
#include <fstream>
#include <algorithm>
using namespace std;
using namespace chrono;//邻接链表:储存无向图
vector<list<int> > adjList;//每个结点
struct Node {int parent; //父结点int wMax;   //以每个结点为树根的最大连通分支权值 int level;  //层次 bool visit; //是否被访问过
};Node* node = NULL;
vector<int> List;//广度优先搜索:用于确定所有结点的level和parent
void bfs()
{queue<int> que;      //队列 que.push(1);         //以结点1为树根 node[1].parent = 0;node[1].visit = 1;while(!que.empty()){int cur = que.front();List.push_back(cur);que.pop();for(list<int>::iterator it = adjList[cur].begin(); it != adjList[cur].end(); ++it){if(!node[*it].visit){node[*it].parent = cur;node[*it].level = node[cur].level + 1; //后代的层次 = parent层次 + 1 que.push(*it);node[*it].visit = 1;}}}
}//自定义比较函数:按level降序排列
bool cmp(const Node& a, const Node& b) {return a.level > b.level;
}int main()
{auto start = system_clock::now();ifstream src("20.txt");int n;src >> n;adjList.assign(n+1, list<int>()); //邻接表:n+1个list<int>构成的vector node = new Node[n+1]; //n+1个 //初始化所有wMax为结点的权值 for(int i = 1; i <= n; ++i){src >> node[i].wMax;node[i].level = 0;node[i].visit = 0;}//将(u, v)和(v, u)加入adjList int u, v;for(int i = 1; i < n; ++i){src >> u >> v;adjList[u].push_back(v);adjList[v].push_back(u);}src.close();bfs(); //广度优先搜索:用于确定所有结点的level和parent//自底向上:依次求出以每个结点为树根的最大连通分支权值 for(int i = 0; i < n; ++i){int parent = node[List[n-1-i]].parent;if(node[i].wMax > 0)node[parent].wMax += node[i].wMax;}//遍历所有结点的wMax,取最大值作为最终结果输出 int maxValue = -INT_MAX;for(int i = 1; i <= n; ++i)maxValue = max(maxValue, node[i].wMax);ofstream out("result.txt");out << maxValue;out.close();auto end = system_clock::now();auto duration = duration_cast<microseconds>(end - start);cout <<  "Problem size: " << n << "\nRunning time: " << double(duration.count()) * microseconds::period::num / microseconds::period::den << "s";return 0;
}

树的最大连通分支问题相关推荐

  1. 算法设计——用分治法查找数组元素的最大值和最小值、用分治法实现合并排序、最小费用问题、树的最大连通分支问题(代码实现)

    代码链接:pan.baidu.com/s/15inIth8Vl89R1CgQ_wYc2g  提取码:gf13 算法分析与设计第 1 次实验 时间 2020.3.31 地点 软件大楼 127 实验名称 ...

  2. 算法实现——树的最大连通分支问题

    问题描述 我们每次在进行权重的加和之前可以事先判断一下权重是否为负数: ·w[k]<0:直接跳过这个顶点k ·w[k]>=0:假设sum(k)是以k为根节点的树的最大连通子图的权值,那么有 ...

  3. 牛客-计算机复试题-求图的连通分支数

    求图的连通分支数可以用并查集实现. 并查集的讲解推荐: https://blog.csdn.net/liujian20150808/article/details/50848646 本题求的是无向图的 ...

  4. 无向图的连通分支数(并查集)

    目录 这是牛客网上题号为 KY268 的一道题 题目描述:该题的目的是要你统计图的连通分支数. 输入描述:每个输入文件包含若干行,每行两个整数 i, j,表示节点 i 和 j 之间存在一条边. 输出描 ...

  5. 离散数学知识点【复试】

    1.极大项是析取,极小项是合取. 2.每个极小项只有一组成真赋值,因此可用于给极小项编码.编码规律为:命题变元与1对应,命题变元的否定与0对应. 3.每个极大项只有一组成假赋值,因此可用于给极大项编码 ...

  6. hdu 4612 边连通度缩点+树的最长路径

    思路:将以桥为分界的所有连通分支进行缩点,得到一颗树,求出树的直径.再用树上的点减去直径,再减一 #pragma comment(linker, "/STACK:1024000000,102 ...

  7. 现代图论笔记(二)树与二分图

    写在前面 这次介绍一些树和二分图的定义和主要性质, 以及这两种结构中常用的算法, 包括二分图的判定, 最小生成树的寻找等. 好久才更新, 只能说自己的代码能力还有欠缺, 一些算法知道思路但就是写不出来 ...

  8. c语言编程求无向图的连通分支,无向图的连通分支

    虽然暂时用不到,还是花时间学习了一下,看网上玩ACM的大牛们都在做图论的题目,我也眼红了... 因为需要用到求强连通分量来判断AOE/PERT中的环路,先研究研究无向图的双连通分量. 对今天的学习做个 ...

  9. 离散数学:连通分支数

    问题描述: 无向图,计算图的最大度.最小度和连通分支数. 图的最大度指的是图中所有结点的度的最大值,图的最小度指的是图中所有结点的度的最小值. 输入 第一行是一个整数V,表示图有V个结点,结点编号0, ...

最新文章

  1. 【加强版】js原生实现拖拽效果,这次没有用document的mousedown、mousemove、mouseup事件我们来点实际的(但是有个弊端:拖拽过程中鼠标会变成一个禁用符号,不太友好)
  2. 韩系春装搭配 穿出优雅气质
  3. OSTimeTick()函数解析
  4. Swift 3 0 FMDB 初试
  5. php三级实例,三级联动实例
  6. php 自动寻路算法,PHP树-不需要递归的实现方法
  7. windows操作系统_windows操作系统如何格式化u盘【操作方法】
  8. 2018年度人工智能优化商业运作的10大途径
  9. jieba分词_wordcloud词云美化——jieba结巴中文分词(将长句拆分)
  10. SpringBoot-源码阅读
  11. 老男孩大趴会笔记分享
  12. Linux常用shell脚本
  13. android开机画面大集合,汇总各种Android 开机画面修改方法 第二屏
  14. 计算机网络——自顶向下
  15. 小米笔记本Air13.3加装固态硬盘
  16. netkeeper错误代码81_netkeeper移动校园宽带客户端错误代码118怎么回事?
  17. 今天睡眠质量记录88分
  18. PHP二次元风格发卡系统源码荔枝发卡网
  19. 安卓和IOS时间解析时间格式不一致的问题
  20. vue3.0+ts+element-plus多页签应用模板:项目搭建

热门文章

  1. 阿里云DevOps助理工程师认证题库和笔记(ACA)2021最新
  2. TP6使用守护进程完成队列任务
  3. 新浪微博开放平台开发
  4. css英文字体 在线引用,css字体英文名称(示例代码)
  5. 微信公众号检测本地App, 安装则打开,未安装则下载的实现方式
  6. 信号完整性问题的11个基本原则(伯格丁原则)
  7. 系统安全 - windowns系统镜像下载
  8. 一个用python实现的东方时尚(驾校)抢课程序
  9. 科大讯飞麦克风阵列AIUI开放平台基本操作初级
  10. C++ 数学与算法系列之高斯消元法求解线性方程组