[问题描述]

有N个城市正在举办厨艺大赛,这些城市的编号为1~N,城市之间有N-1条道路相连,并且城市之间两两可达。每个城市i都有一个里程值Ai:从城市X出发,要达到城市Y的必要条件是存在一条从X到Y的简单路径,且该路径恰好有Ax条边。

为了尽可能多地参加各地比赛,假设你可以从任意城市出发,且可以访问任意城市多次,求最多可以参加多少场比赛。

严格来说,给定一棵树,其中每个节点有权值Ai,如果我们可以从任意节点出发,并经过任意节点多次,你需要求出最多可以到达的城市数量,唯一条件是从i移动到j当且仅当i到j的简单路径上恰好有Ai条边。

[输入格式]

+ 第一行包含N

+ 接下来N-1行包含u,v表示一条边

+ 接下来一行包含N个整数Ai

[输出格式]

输出最多可以访问多少不同的城市

[补充说明]

+ 1≤ui≤N,1≤vi≤N,且ui≠vi

+ 保证输入是树

[样例1]

输入:

5

1 3

3 5

1 4

4 2

1 2 3 3 1

输出:

5

[样例2]

输入:

8

1 5

1 6

1 7

1 8

1 2

2 3

3 4

1 2 3 4 5 6 7 8

思考与解释:

首先解释一下题目的意思:N个城市,城市之间有N-1条道路相连,并且城市之间两两可达。若把它视为一张图,则该图连通且 边数=顶点数 - 1,可以得出该图连通且不含回路(根据离散数学中的知识,这里不多加解释),即该图为树。简单路径则是指通路中所有边互不相同。举例:假设A1点的里程值为2,则A1可以到达的城市必须和A1有一条包含两条边的简单路径。

解题方法:

1、求出每个点可以到达的城市。我们先构建原图(由于树也是图的一种,这里我们统一用图来处理),再利用BFS,限定广搜的范围(即搜到第几条边停下),在最后一次搜索时,遍历到的点即为可以到达的点。

2、构建新图。在可以到达的城市间建立边(有向,因为有A1->A2,但不一定有A2->A1),这样就形成了一张新图(注意新图不一定所有点都连通)。

3、在新图中找出包含点数目最多的单向连通图(有向图D中任意两个顶点至少一个可达另一个,则称D是单向连通图)。这个单向连通图包含的顶点数即为最终结果。依次从各点出发,采用深度优先遍历,把经过的边删掉,当一个顶点无法继续向下遍历时,将此时已经过的顶点数与res比较,取最大值。最后的res即为最终结果。

程序代码:

# include <iostream>
# include <stdlib.h>
# include <algorithm>
# include <queue>
# define SIZE 1024using namespace std;typedef struct ArcNode {      //边的结点结构类型int adjvex;               //该边的终点编号struct ArcNode* nextarc;  //指向下一条边的指针
}ArcNode;
typedef struct VexNode {  //顶点结构int num;              //顶点序号int x;                //顶点的里程值ArcNode* firstarc;    //指向第一条与该顶点有关的边的指针
}VexNode;
typedef struct Graph {    //邻接表结构类型VexNode* VNode;       //定义邻接表int vexnum, arcnum;   //顶点数和边的个数int type;             //图的种类(1:无向图 2:有向图)
}Graph;int res = 0;             //最终结果
int Visit[SIZE] = { 0 }; //辅助数组,标记点是否已被访问过
int A[SIZE] = { 0 };     //各点的里程值
int Arc[SIZE][2];        //边
int newarc = 0;          //新图的边数
void CreateGraph(Graph& G);        //创建图
void BFS(Graph G1, int n, int m);  //n:顶点编号 m:广搜的深度
void BFSGraph(Graph G1);           //对G1广度优先遍历,求出每个顶点可以到达的城市
void DFS(Graph G2, int n, int m);  //n:顶点编号 m:经过点的数目
void DFSGraph(Graph G2);           //对G2深度优先遍历,求出从每个顶点出发最多可以到达的城市数int main()
{Graph G1, G2;  //G1是原图,G2是新图G1.type = 1;   //G1是无向图cin >> G1.vexnum;G1.arcnum = G1.vexnum - 1;for (int i = 1; i <= G1.arcnum; i++){//输入边cin >> Arc[i][0] >> Arc[i][1];}for (int i = 1; i <= G1.vexnum; i++){//输入各点的里程值cin >> A[i];}CreateGraph(G1);  //构建G1//重新初始化for (int i = 1; i <= G1.arcnum; i++){Arc[i][0] = 0;Arc[i][1] = 0;}for (int i = 1; i <= G1.vexnum; i++){A[i] = 0;}BFSGraph(G1);    //求G2的边G2.type = 2;     //G2是有向图G2.vexnum = G1.vexnum;G2.arcnum = newarc;CreateGraph(G2); //构建G2DFSGraph(G2);cout << res << endl;return 0;
}//创建图
void CreateGraph(Graph& G)
{G.VNode = (VexNode*)malloc(SIZE * sizeof(VexNode));for (int i = 1; i <= G.vexnum; i++){//邻接表初始化,所有单向链表均为空表,同时初始化里程值G.VNode[i].firstarc = NULL;G.VNode[i].x = A[i];}int x, y;    //x:起始点,y:终点ArcNode* p, * q;for (int i = 1; i <= G.arcnum; i++){x = Arc[i][0];y = Arc[i][1];p = (ArcNode*)malloc(sizeof(ArcNode)); //创建一个用于存放当前边的结点pp->nextarc = NULL;p->adjvex = y;q = G.VNode[x].firstarc;//将边按顺序插入到链表末尾if (q == NULL){G.VNode[x].firstarc = p;}else{while (q->nextarc != NULL){q = q->nextarc;}q->nextarc = p;}if (G.type == 1){//如果是无向图,要再创建一个表示对称边的结点pp = (ArcNode*)malloc(sizeof(ArcNode));p->nextarc = NULL;p->adjvex = x;q = G.VNode[y].firstarc;if (q == NULL){G.VNode[y].firstarc = p;}else{while (q->nextarc != NULL){q = q->nextarc;}q->nextarc = p;}}}
}//n:顶点编号 m:广搜的深度
void BFS(Graph G1, int n, int m)
{queue<int>Q;Visit[n] = 1;  //将起始点标记为已被访问过的状态Q.push(n);     //起始点入队int k = 0;     //追踪遍历的范围int s1 = 1, s2 = 0;//s1:当前层元素个数 s2:下一层元素个数int a;             //跟踪顶点while (!Q.empty()){if (k == m){//已达到范围break;}while (!Q.empty() && s1){a = Q.front();        //队头元素出队Q.pop();ArcNode* p = G1.VNode[a].firstarc;while (p){//遍历当前队头结点的所有邻接点,若邻接点已被访问过,则p继续向后遍历//否则入队,并标记为已访问状态,防止重复入队if (!Visit[p->adjvex]){if (k == m - 1){newarc++;Arc[newarc][0] = n;Arc[newarc][1] = p->adjvex;}Visit[p->adjvex] = 1;Q.push(p->adjvex);s2++;}p = p->nextarc;}s1--;}k++;s1 = s2;s2 = 0;}
}//对G1广度优先遍历,求出每个顶点可以到达的城市
void BFSGraph(Graph G1)
{for (int i = 1; i <= G1.vexnum; i++){//辅助数组初始化for (int j = 1; j <= G1.vexnum; j++){Visit[j] = 0;}//对每一个顶点均调用一次广度优先遍历,限定范围为顶点的里程值BFS(G1, i, G1.VNode[i].x);}
}//n:顶点编号 m:经过点的数目
void DFS(Graph G2, int n, int m)
{int k, t = 1;ArcNode* p = G2.VNode[n].firstarc;while (p){//遍历起始点的所有邻接点,若邻接点已被访问过,则p继续向后遍历//否则,以当前邻接点为新的起始点递归进行深度优先遍历if (p->adjvex > 0){t = 0;k = p->adjvex;if (!Visit[k]){Visit[k] = 1;//把经过的边删除p->adjvex = 0;DFS(G2, k, m + 1);p->adjvex = k;Visit[k] = 0;}else{//把经过的边删除p->adjvex = 0;DFS(G2, k, m);p->adjvex = k;}}p = p->nextarc;}if (t){res = max(res, m);}
}//对G2深度优先遍历,求出从每个顶点出发最多可以到达的城市数
void DFSGraph(Graph G2)
{for (int i = 1; i <= G2.vexnum; i++){//辅助数组初始化for (int j = 1; j <= G2.vexnum; j++){Visit[j] = 0;}//对每一个顶点均调用一次深度优先遍历Visit[i] = 1;DFS(G2, i, 1);}
}

运行示例:

8
1 5
1 6
1 7
1 8
1 2
2 3
3 4
1 2 3 4 5 6 7 8
4

以上便是我对这道题的看法,很高兴与大家分享。

城市巡游赛(树和图)相关推荐

  1. A城市巡游车与网约车运营特征对比分析—赛题介绍与准备工作

    赛题介绍 2020数字中国创新大赛 赛题说明 出租车作为城市客运交通系统的重要组成部分,以高效.便捷.灵活等优点深受居民青睐.出租车每天的运营中会产生大量的上下车点位相关信息,对这些数据进行科学合理的 ...

  2. echart关系树状图_干货 | 25个常用Matplotlib图的Python代码

    50个Matplotlib图的汇编,在数据分析和可视化中最有用.此列表允许您使用Python的Matplotlib和Seaborn库选择要显示的可视化对象. 1.关联 散点图 带边界的气泡图 带线性回 ...

  3. 数据结构与算法一览(树、图、排序算法、搜索算法等)- Review

    算法基础简介 - OI Wiki (oi-wiki.org) 文章目录 1. 数据结构介绍 1.1 什么是数据结构 1.2 数据结构分类 2. 链表.栈.队列:略 3. 哈希表:略 4. 树 4.1 ...

  4. python中plotly绘制树地图_聚类分析python画树状图--Plotly(dendrogram)用法解析 - 人人都是架构师...

    1.前言 聚类分析是机器学习和数据分析中非常常见的分类方法, 当我们用到层次聚类(系统聚类)时,最常用的分析方法就是绘制树状图, 比较常见的统计软件像SPSS.SAS.R等都可以直接绘制树状图,比较简 ...

  5. MATLAB | 全网唯一,使用MATLAB绘制精致的环形树状图

    绘制效果 请叫我平平无奇的绘图天才,这期一次性带来俩工具函数,分别是两层和三层的环形树状图,可以用来展示数据分类和层级: 理顺层级关系属实理得头秃,代码编写不易点个赞叭!! 由于工具函数过长,将被放在 ...

  6. 《大话数据结构》6、7树、图

    第6章树 149 树: 树 (Tree) 是 n (n>=0) 个结点的有限集 . n=0 时称为空树. 在任意一棵非空 树中: ( 1 ) 有旦仅有一个特定的称为根 (Root) 的结点: ( ...

  7. bzoj 4871: [Shoi2017]摧毁“树状图”

    4871: [Shoi2017]摧毁"树状图" Time Limit: 25 Sec  Memory Limit: 512 MB Submit: 53  Solved: 9 [Su ...

  8. 0x21.搜索 - 树与图的遍历、拓扑排序

    目录 一.树与图的深度优先遍历及树的一些性质 1.树与图的深度优先遍历 2.时间戳 3.树的DFS序(树链剖分前驱知识) 4.树的深度 5.树的重心与sizesizesize 6.图的连通块划分 二. ...

  9. R语言绘制环形树状图

    R语言绘制环形树状图 1.主要用到dendextend和circlize包绘图: library(dendextend) library(circlize)# 距离矩阵 d <- dist(US ...

最新文章

  1. 小程序点击按钮 关闭小程序
  2. python 守护程序检测进程是否存在_python创建守护进程的疑问
  3. 获取JavaScript变量的类型
  4. Sharepoint2007个人网站不能同步域信息的处理方法
  5. debian下添加环境变量
  6. Dijkstra求最短路 II
  7. 华为云跻身Gartner报告中国三强,预示云计算市场的未来变局?
  8. Memcached源码分析之memcached.h
  9. 安卓打开本应用的应用信息界面的代码
  10. c语言怎么设计程序框图,C语言课程设计————写下流程图! 谢谢
  11. nupkg 本地安装_使用Nuget安装脱机软件包nupkg
  12. windows freeSSHd搭建SFtp服务器
  13. 机械电子工程专业和计算机科学,机械电子工程专业属于什么类别
  14. word没有显示endnote_word 未显示EndNote工具条的解决方法
  15. 疯狂的程序员 41-50
  16. 百度编辑器嵌套秀米编辑器遇到的问题
  17. PGN: 指针生成网络(Get To The Point: Summarization with Pointer-Generator Networks)
  18. 好用看得见!深度操作系统Deepin装机使用体验
  19. 利用腾讯云函数做蓝奏云解析API
  20. 怎么把html设置桌面壁纸,win7系统怎么把桌面更换成自己喜欢的桌面背景?

热门文章

  1. Mysql之limit语句
  2. 电脑端破解之破解注册码
  3. 用 Python 开发简单交互式 Web 应用
  4. 严厉打击恶意劫持 百度移动搜索推出烽火算法2.0
  5. mysql 悲观锁实现
  6. javaSocket基础
  7. 大数据Hadoop系列之HDFS命令讲解
  8. React 环境搭建以及创建项目工程(一)
  9. Job-shop和Flow-shop区别
  10. 常用的激活函数sigmoid,relu,tanh