城市巡游赛(树和图)
[问题描述]
有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
以上便是我对这道题的看法,很高兴与大家分享。
城市巡游赛(树和图)相关推荐
- A城市巡游车与网约车运营特征对比分析—赛题介绍与准备工作
赛题介绍 2020数字中国创新大赛 赛题说明 出租车作为城市客运交通系统的重要组成部分,以高效.便捷.灵活等优点深受居民青睐.出租车每天的运营中会产生大量的上下车点位相关信息,对这些数据进行科学合理的 ...
- echart关系树状图_干货 | 25个常用Matplotlib图的Python代码
50个Matplotlib图的汇编,在数据分析和可视化中最有用.此列表允许您使用Python的Matplotlib和Seaborn库选择要显示的可视化对象. 1.关联 散点图 带边界的气泡图 带线性回 ...
- 数据结构与算法一览(树、图、排序算法、搜索算法等)- Review
算法基础简介 - OI Wiki (oi-wiki.org) 文章目录 1. 数据结构介绍 1.1 什么是数据结构 1.2 数据结构分类 2. 链表.栈.队列:略 3. 哈希表:略 4. 树 4.1 ...
- python中plotly绘制树地图_聚类分析python画树状图--Plotly(dendrogram)用法解析 - 人人都是架构师...
1.前言 聚类分析是机器学习和数据分析中非常常见的分类方法, 当我们用到层次聚类(系统聚类)时,最常用的分析方法就是绘制树状图, 比较常见的统计软件像SPSS.SAS.R等都可以直接绘制树状图,比较简 ...
- MATLAB | 全网唯一,使用MATLAB绘制精致的环形树状图
绘制效果 请叫我平平无奇的绘图天才,这期一次性带来俩工具函数,分别是两层和三层的环形树状图,可以用来展示数据分类和层级: 理顺层级关系属实理得头秃,代码编写不易点个赞叭!! 由于工具函数过长,将被放在 ...
- 《大话数据结构》6、7树、图
第6章树 149 树: 树 (Tree) 是 n (n>=0) 个结点的有限集 . n=0 时称为空树. 在任意一棵非空 树中: ( 1 ) 有旦仅有一个特定的称为根 (Root) 的结点: ( ...
- bzoj 4871: [Shoi2017]摧毁“树状图”
4871: [Shoi2017]摧毁"树状图" Time Limit: 25 Sec Memory Limit: 512 MB Submit: 53 Solved: 9 [Su ...
- 0x21.搜索 - 树与图的遍历、拓扑排序
目录 一.树与图的深度优先遍历及树的一些性质 1.树与图的深度优先遍历 2.时间戳 3.树的DFS序(树链剖分前驱知识) 4.树的深度 5.树的重心与sizesizesize 6.图的连通块划分 二. ...
- R语言绘制环形树状图
R语言绘制环形树状图 1.主要用到dendextend和circlize包绘图: library(dendextend) library(circlize)# 距离矩阵 d <- dist(US ...
最新文章
- 小程序点击按钮 关闭小程序
- python 守护程序检测进程是否存在_python创建守护进程的疑问
- 获取JavaScript变量的类型
- Sharepoint2007个人网站不能同步域信息的处理方法
- debian下添加环境变量
- Dijkstra求最短路 II
- 华为云跻身Gartner报告中国三强,预示云计算市场的未来变局?
- Memcached源码分析之memcached.h
- 安卓打开本应用的应用信息界面的代码
- c语言怎么设计程序框图,C语言课程设计————写下流程图! 谢谢
- nupkg 本地安装_使用Nuget安装脱机软件包nupkg
- windows freeSSHd搭建SFtp服务器
- 机械电子工程专业和计算机科学,机械电子工程专业属于什么类别
- word没有显示endnote_word 未显示EndNote工具条的解决方法
- 疯狂的程序员 41-50
- 百度编辑器嵌套秀米编辑器遇到的问题
- PGN: 指针生成网络(Get To The Point: Summarization with Pointer-Generator Networks)
- 好用看得见!深度操作系统Deepin装机使用体验
- 利用腾讯云函数做蓝奏云解析API
- 怎么把html设置桌面壁纸,win7系统怎么把桌面更换成自己喜欢的桌面背景?