现在的位置: 首页 > 综合 > 正文

UVa Problem 10199 Tourist Guide (导游)

2012年03月26日 ⁄ 综合 ⁄ 共 4399字 ⁄ 字号 评论关闭
// Tourist Guide (导游)
// PC/UVa IDs: 111006/10199, Popularity: B, Success rate: average Level: 3
// Verdict: Accepted
// Submission Date: 2011-10-07
// UVa Run Time: 0.040s
//
// 版权所有(C)2011,邱秋。metaphysis # yeah dot net
//
// [Problem Description]
// Rio de Janeiro is a very beautiful city, but there are so many places to visit
// that you feel overwhelmed, Fortunately, your friend Bruno has promised to be
// your tour guide.
//
// Unfortunately, Bruno is terrible driver. He has a lot of traffic fines to pay
// and is eager to avoid paying more. Therefore he wants to know where all the
// police cameras are located so he can drive more carefully when passing by them.
// These cameras are strategically distributed over the city, in locations that
// a driver must pass through in order to travel from one zone of the city to
// another. A location C will have a camera if and only if there are two city
// locations A and B such that all paths from A to B pass through a location C.
//
// For instance, suppose that we have six locations (A, B, C, D, E, and F ) with
// seven bidirectional routes B − C, A − B, C − A, D − C, D − E, E − F , and F − C.
// There must be a camera on C because to go from A to E you must pass through C.
// In this configuration, C is the only camera location.
//
// Given a map of the city, help Bruno avoid further fines during your tour by
// writing a program to identify where all the cameras are.
//
// [Input]
// The input will consist of an arbitrary number of city maps, where each map
// begins with an integer N (2 < N ≤ 100) denoting the total number of locations
// in the city. Then follow N different place names at one per line, where each
// place name will consist of least one and at most 30 lowercase letters. A
// non-negative integer R then follows, denoting the total routes of the city.
// The next R lines each describe a bidirectional route represented by the two
// places that the route connects.
//
// Location names in route descriptions will always be valid, and there will be
// no route from one place to itself. You must read until N = 0, which should not
// be processed.
//
// [Output]
// For each city map you must print the following line:
//
// City map #d: c camera(s) found
//
// where d stands for the city map number (starting from 1) and c stands for the
// total number of cameras. Then should follow c lines with the location names
// of each camera in alphabetical order. Print a blank line between output sets.
//
// [Sample Input]
// 6
// sugarloaf
// maracana
// copacabana
// ipanema
// corcovado
// lapa
// 7
// ipanema copacabana
// copacabana sugarloaf
// ipanema sugarloaf
// maracana lapa
// sugarloaf maracana
// corcovado sugarloaf
// lapa corcovado
// 5
// guanabarabay
// downtown
// botanicgarden
// colombo
// sambodromo
// 4
// guanabarabay sambodromo
// downtown sambodromo
// sambodromo botanicgarden
// colombo sambodromo
// 0
//
// [Sample Output]
// City map #1: 1 camera(s) found
// sugarloaf
//
// City map #2: 1 camera(s) found
// sambodromo
//
// [解题方法]
// 摄像头的位置对应图论的割顶(articulation vertex)概念,求图的割顶即可,需要注意的是,测试数
// 据所给的可能不是连通图,故需要找到其中的所有连通子图的割顶。

#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>

using namespace std;

#define MAXV 100

string locations[MAXV + 1];
int edges[MAXV + 1][MAXV + 1];
int degree[MAXV + 1];
int nvertices;
bool discovered[MAXV + 1];

// 深度优先遍历。
void dfs(int start)
{
	discovered[start] = true;
	nvertices++;
	
	for (int i = 0; i < degree[start]; i++)
		if (discovered[edges[start][i]] == false)
			dfs(edges[start][i]);
}

// 求连通图的割顶。
void articulation_vertex(vector < int > &component, vector < string > &cameras)
{
	int ncomponent = component.size();

	for (int i = 0; i < ncomponent; i++)
	{
		nvertices = 0;
		memset(discovered, 0, sizeof(discovered));
		discovered[component[i]] = true;

		dfs(i < (ncomponent - 1) ? component[i + 1] : component[i - 1]);

		if (nvertices < (ncomponent - 1))
			cameras.push_back(locations[component[i]]);	
	}
}

int main(int ac, char *av[])
{
	int cases = 1, ncities, routes;
	string location, start, end;
	
	while (cin >> ncities, ncities)
	{
		map < string, int > cityMap;
		for (int i = 1; i <= ncities; i++)
		{
			cin >> location;
			cityMap[location] = i;
			degree[i] = 0;
			locations[i] = location;
		}

		cin >> routes;
		for (int i = 1; i <= routes; i++)
		{
			cin >> start >> end;
			edges[cityMap[start]][degree[cityMap[start]]++] = cityMap[end];
			edges[cityMap[end]][degree[cityMap[end]]++] = cityMap[start];
		}
		
		// 找出所有连通子图,并求其割顶。
		bool visited[MAXV + 1];
		memset(visited, 0, sizeof(visited));
		vector < string > cameras;

		for (int i = 1; i <= ncities; i++)
			if (visited[i] == false)
			{
				queue < int > vertices;
				vector < int > component;

				vertices.push(i);
				visited[i] = true;
				component.push_back(i);
				
				while (!vertices.empty())
				{
					int v = vertices.front();
					vertices.pop();
					
					for (int i = 0; i < degree[v]; i++)
						if (visited[edges[v][i]] == false)
						{
							vertices.push(edges[v][i]);
							visited[edges[v][i]] = true;
							component.push_back(edges[v][i]);
						}
				}
				
				// 求连通子图的割顶。
				articulation_vertex(component, cameras);
			}

		// 输出。
		if (cases > 1)
			cout << endl;
		sort(cameras.begin(), cameras.end());	
		cout << "City map #" << cases++ << ": ";
		cout << cameras.size() << " camera(s) found" << endl;
		for (int i = 0; i < cameras.size(); i++)
			cout << cameras[i] << endl;
	}

	return 0;
}

抱歉!评论已关闭.