UVa OJ 140 - Bandwidth (带宽)
Time limit: 3.000 seconds
限时3.000秒
Problem
问题
Given a graph (V,E) where V is a set of nodes and E is a set of arcs in VxV, and an ordering on the elements in V, then the bandwidth of a node v is defined as the maximum distance in the ordering between v and any node to which it is connected in the graph. The bandwidth of the ordering is then defined as the maximum of the individual bandwidths. For example, consider the following graph:
给定一个图(V,E),其中V为顶点的集合,E为边的集合,属于VxV。给定V中元素的一种排序,那么顶点v的带宽定义如下:在当前给定的排序中,与v距离最远的且与v有边相连的顶点与v的距离。给定排序的带宽定义为各顶点带宽的最大值。例如考虑如下图:

This can be ordered in many ways, two of which are illustrated below:
此图可以给出多种排序,其中两个排序图示如下:

For these orderings, the bandwidths of the nodes (in order) are 6, 6, 1, 4, 1, 1, 6, 6 giving an ordering bandwidth of 6, and 5, 3, 1, 4, 3, 5, 1, 4 giving an ordering bandwidth of 5.
对于给出的这两个排序,它们各结点的带宽分别是(按排序顺序):6, 6, 1, 4, 1, 1, 6, 6,排序带宽为6,以及5, 3, 1, 4, 3, 5, 1, 4,排序带宽为5。
Write a program that will find the ordering of a graph that minimises the bandwidth.
写一个程序,找出该图的一种排序使其带宽最小。
Input
输入
Input will consist of a series of graphs. Each graph will appear on a line by itself. The entire file will be terminated by a line consisting of a single#. For each graph, the input will consist of a series of records separated by `;'. Each record will consist of a node name (a single upper case character in the the range `A' to `Z'),followed by a `:' and at least one of its neighbours. The graph will contain no more than 8 nodes.
输入由一系列的图构成。每个图独占一行。一个仅包含“#”字符的一行输入标志整个输入文件结束。对于每个图的输入,都包含一系列由“;”隔开的记录。每个记录包含一个结点名(一个大写字母,范围是“A”到“Z”),接着是一个“:”,然后是一些该结点的邻居结点。图中不会包含超过8个结点。
Output
输出
Output will consist of one line for each graph, listing the ordering of the nodes followed by an arrow (->) and the bandwidth for that ordering. All items must be separated from their neighbours by exactly one space. If more than one ordering produces the same bandwidth, then choose the smallest in lexicographic ordering, that is the one that would appear first in an alphabetic listing.
每个图对应一行输出,列出排序的结点,然后是一个箭头(->)以及该排序的带宽值。所有项都应由一个空格与它相邻的项隔开。如果同一个带宽有多种排序方法,取字母序最小的一种排序,也就是取字母表排在前面的一种排序。
Sample input
示例输入
A:FB;B:GC;D:GC;F:AGH;E:HD
#
Analysis
分析
典型的优化问题,一个可行解就是一个排序,目标函数就是解的带宽。但ACM的优化问题一定是使用确定性算法的(与包含随机元素的现代优化算法如遗传、粒子相对),确定性优化算法就那么几种,贪心、动态规划、单纯行(解线性规划)还有就是暴力。注意到题中专门强调:图不会超过8个结点,结点的名字都是从“A”到“Z”,相同带宽的排序取字典序靠前等,所有的线索都指向了一种算法:暴力搜索。
从要求的“字典序”得到启发:全排列生成算法。剩下的问题就是以何种数据结构来存储,以便快速的查找顶点和计算带宽。对于一种顶点的排序,要查找指定顶点所在的位置,最快的方法就是使用标记数组。由于题中限定的顶点的取值范转:“A”到“Z”,因此用一个26个元素的数组即可记录每个顶点在排序中的位置。
记下顶点的位置后,需要用最快的方式查出每个顶点到它的邻居的距离,这实际就是在当前排序中找出相距最远的一条边。因此只要遍历图中所有的边,计算其在当前排序中的距离,并记录最远的距离即可。图可以用边的集合来表示图,每个边用两个顶点来表示。由于是无向图,因此可使边的两个顶点程左小右大排序,然后保证无重边即可。
Solution
解答
#include "stdafx.h"
#include <algorithm>
#include <iostream>
#include <vector>
#include <string> typedef std::pair<char, char> NODEPAIR;
typedef std::vector<char>::iterator NODE_ITER;
typedef std::string::iterator STR_ITER;
typedef std::vector<NODEPAIR>::iterator GRAPH_ITER; int main(void)
{
char idxTbl[32]; // 从顶点编号到其在某种排序中的位置的对应表
std::string strLine; // 存储一行输入的字符串
for (; std::getline(std::cin, strLine) && strLine[0] != '#'; ) {
std::vector<NODEPAIR> graph; // 数组中每个元素为一条边,用一对顶点的编号表示
std::vector<char> nodes; // 记录一种顶点的排序
// 为方便判断一行输入的结束,在行层添加分号
strLine.push_back(';');
// 循环处理当前输入行的每一个字符
for (STR_ITER i = strLine.begin(); i != strLine.end(); ++i) {
// 用所有边的顶点对来表示图,nFrom是冒号前的顶点,nTo是冒号后的顶点
char nFrom = *i - 'A'; // 每个顶点的编号为其字母的ASCII码-'A'
// 有些顶点只出现在冒号前,有些只出现在冒号后,因此nFrom和nTo都需添加
nodes.push_back(nFrom);
// 遍历冒号后面直到分号的顶点,这些顶点用nTo表示
for (i += 2; *i != ';'; ++i) {
char nTo = *i - 'A'; // 每个顶点的编号为其字母的ASCII码-'A'
nodes.push_back(nTo);
// 保证添加到图中的顶点对(边)中编号较小的顶点在前,避免无向图的重复边
if (nFrom > nTo)
graph.push_back(NODEPAIR(nFrom, nTo));
else if (nFrom < nTo)
graph.push_back(NODEPAIR(nTo, nFrom));
}
}
// 对图的所有顶点对(边)排序去重
std::sort(graph.begin(), graph.end());
graph.erase(std::unique(graph.begin(), graph.end()), graph.end());
// 对顶点数组排序去重,作为第一种排序(升序最小)
std::sort(nodes.begin(), nodes.end());
nodes.erase(std::unique(nodes.begin(), nodes.end()), nodes.end());
std::vector<char> minOrder; // 记录具有最小带宽的排序
char nMinBw = char(nodes.size()); // 记录具有最小的带宽,初始化为数组长度
for (bool bNext = true; bNext; ) { // 遍历所有排序
char nCnt = 0, nOrderBw = 0;
// 扫描一遍当前的排序,求出每一个顶点在当前排序中的位置
for (NODE_ITER i = nodes.begin(); i != nodes.end(); ++i) {
idxTbl[*i] = nCnt++;
}
// 遍历图中的所有顶点对,找出在当前排序中距离最远的顶点对作为当前排序的带宽
for (GRAPH_ITER i = graph.begin(); i != graph.end(); ++i) {
char nCur = char(std::abs(idxTbl[i->first] - idxTbl[i->second]));
if (nCur > nOrderBw)
nOrderBw = nCur;
}
// 如果当前排序的带宽小于已知最小带宽,则更新最小带宽和最小排序
if (nOrderBw < nMinBw) {
nMinBw = nOrderBw;
minOrder = nodes;
}
// 接字母序给出下一种排序
bNext = std::next_permutation(nodes.begin(), nodes.end());
}
// 按格式循环输出最小排序和它的带宽值
for (NODE_ITER i = minOrder.begin(); i != minOrder.end(); ++i) {
std::cout << char(*i + 'A') << ' ';
}
std::cout << "-> " << (int)nMinBw << std::endl;
}
return 0;
}
UVa OJ 140 - Bandwidth (带宽)的更多相关文章
- UVA - 140 Bandwidth(带宽)(全排列)
题意:给定图,求是带宽最小的结点排列. 分析:结点数最多为8,全排列即可.顶点范围是A~Z. #pragma comment(linker, "/STACK:102400000, 10240 ...
- uva 140 bandwidth (好题) ——yhx
Bandwidth Given a graph (V,E) where V is a set of nodes and E is a set of arcs in VxV, and an orde ...
- UVa 140 Bandwidth【枚举排列】
题意:给出n个节点的图,和一个节点的排列,定义节点i的带宽b[i]为i和其相邻节点在排列中的最远的距离,所有的b[i]的最大值为这个图的带宽,给一个图,求出带宽最小的节点排列 看的紫书,紫书上说得很详 ...
- UVA 140 Bandwidth
题意: 给出一个n个节点的图G,和一个节点的排列,定义节点i的带宽为i和相邻节点在排列中的最远距离,而所有带宽的最大值就是图的带宽,求让图的带宽最小的排列. 分析: 列出所有可能的排列,记录当前找到的 ...
- UVA 140 Bandwidth (dfs 剪枝 映射)
题意: 给定一个n个结点的图G和一个结点的排列, 定义结点i的带宽b(i)为i和相邻结点在排列中的最远距离, 所有b(i)的最大值就是这个图的带宽, 给定G, 求让带宽最小的结点排列. 给定的图 n ...
- UVA - 820 Internet Bandwidth (因特网带宽)(最大流)
题意:给出所有计算机之间的路径和路径容量后,求出两个给定结点之间的流通总容量.(假设路径是双向的,且两方向流动的容量相同) 分析:裸最大流.标号从1开始,初始化的时候注意. #pragma comme ...
- UVA 140 Brandwidth 带宽 (dfs回溯)
看到next_permutation好像也能过╮(╯▽╰)╭ 这题学习点: 1.建图做映射 2.通过定序枚举保证字典序最小 3.strtok,sscanf,strchr等函数又复习了一遍,尽管程序中没 ...
- UVA 820 Internet Bandwidth 因特网宽带(无向图,最大流,常规)
题意:给一个无向图,每条边上都有容量的限制,要求求出给定起点和终点的最大流. 思路:每条无向边就得拆成2条,每条还得有反向边,所以共4条.源点汇点已经给出,所以不用建了.直接在图上跑最大流就可以了. ...
- UVA 820 Internet Bandwidth
题意: 给出双向图,求给出两点的流通总流量. 分析: 网络流中的增广路算法. 代码: #include <iostream>#include <cstring>#include ...
随机推荐
- C语言 共用体
//共用体 union #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #includ ...
- 解决centos7重启后出现ata bus error
昨天把centos7装在电脑上了,还把win7系统格掉了,从此电脑上只装centos,有一种弃暗投明的感觉. 装完重启后欣赏了一番成果,一个halt命令想把系统关掉,却发现屏幕没黑,机器不转了,电源灯 ...
- benchmark
redis benchmark How many requests per second can I get out of Redis? Using New Relic to Understand R ...
- eclipse使用
Eclipse 是一个开放源代码的.基于 Java 的可扩展开发平台. Eclipse 是 Java 的集成开发环境(IDE),当然 Eclipse 也可以作为其他开发语言的集成开发环境,如C,C++ ...
- [CareerCup] 13.1 Print Last K Lines 打印最后K行
13.1 Write a method to print the last K lines of an input file using C++. 这道题让我们用C++来打印一个输入文本的最后K行,最 ...
- 记一次w3wp占用CPU过高的解决过程(Dictionary和线程安全)
项目上线以来一直存在一个比较揪心的问题,和一个没有信心处理的BUG,那就是在应用程序启动时有可能会导致cpu跑满99%或持续在一个值如50%左右,这样一来对服务器的压力是非常大的,经常出现服务器无法远 ...
- jQuery 模板插件jquery-tmpl
Step1:导入脚本: <script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")">&l ...
- C#出题库项目的总结(2)
前记:好吧好吧,我好好的自我检讨,这个总结拖了这么久才来写,而且一周多没有看技术相关的东西,实在罪过,不过因为想做的事情太多,所以时间的分配确实是一个很严肃的问题,不是时间不够用,是我自己没有做好时间 ...
- 将Mininet与真实网络相连接
原文发表在我的博客主页,转载请注明出处 前言 Mininet是SDN网络仿真的一大利器,在小规模网络模拟使用上独领风骚,其开源性允许使用者按照自己的需求修改源码,得到想要的数据,其提供了多个函数用来满 ...
- 【微收藏】来自Twitter的自动文字补齐jQuery插件 - Typeahead.js
没图没逼格 事发有因 该插件可以结合本地数据进行一些操作.推荐关注一下H5的几种数据存储的方式(localstorage与sessionstorage.IndexedDB.离线缓存manifest文件 ...