1. 程式人生 > >C++筆試題 奇妙旅行

C++筆試題 奇妙旅行

奇妙旅行

描述

小熊住在由n個城鎮(城鎮編號from 1 to n)組成的國家裡,n-1條雙向聯通的路將這n個城鎮相互連線。所以從一個城鎮旅行到其他任意一個城鎮都是可行的。小熊想要進行一次旅行,它選擇一對城鎮(u,v)(u ≠ v),然後選擇從u到v的最短路徑完成旅行。(注意:(u,v)和(v,u)被認為是不同旅行。)
然而,在小熊的國家裡,有2個特殊的城鎮,一個叫倫敦(編號x),一個叫巴黎(編號y)。倫敦是一個被花香縈繞的小鎮,巴黎是一個到處都是蜜蜂的小鎮。因此,小熊在旅行過程中,如果先經過倫敦,再經過巴黎,他就會遭到蜜蜂的瘋狂攻擊。
請你幫幫小熊計算出有多少對(u,v)可供選擇來完成旅行計劃。

輸入描述

第一行包含3個整數,n,x,y(1 ≤n≤3000, 1≤x,y≤n , x ≠ y) ,n表示城鎮數量,x表示倫敦的編號,y表示巴黎的編號。
接下來n-1行,每行包括兩個整數a,b(1≤a,b≤n1≤a,b≤n, a≠b),描述了城鎮a和城鎮b之間存在一條道路。
輸入保證,任意兩點都彼此聯通(所給的城鎮和道路組成了一棵樹)。

輸出描述

輸出有多少對(u,v)可供小熊選擇來完成旅行。

樣例輸入 1

3 1 3
1 2
2 3

樣例輸出 1

5

樣例輸入 2

3 1 3
1 2
1 3

樣例輸出 2

4

提示

第一個example中,小熊有5種選擇
(1,2): 他的路線是 1→2
(2,3): 他的路線是 2→3
(3,2): 他的路線是 3→2
(2,1): 他的路線是 2→1
(3,1): 他的路線是 3→2→1
小熊不能選擇(1,3)。因為如果它選擇這個路線,他會先訪問城鎮1(倫敦)再訪問城鎮3(巴黎),它會遭到蜜蜂的攻擊,這會讓小熊受傷。

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <iterator>
#include <climits>    // INT_MAX
#include <algorithm>  // min()
#include <iomanip>    // setw()

using namespace std;
// #define UNIT_TEST // #define PRINT_PATH_INFO // save the shortest Distance information from starting vertex to each vertex struct Distance { string path; vector<int> pathInfo; int value; bool visit; Distance() { visit = false; value = 0; path = ""; } }; class Graph_DG { private: static const int max_weight = numeric_limits<int>::max(); // INT_MAX; int m_vertexLondon; int m_vertexParis; int m_vertexNum; int m_edgeNum; int **m_adjacentMatrix; Distance *m_distance; string convertInt2String(int n); bool check_edgeNum_value(int vertexIn, int vertexOut, int weight); set<int> m_vertexInSet; set<int> m_vertexOutSet; void generateGraphDat(); void createGraph(); void Dijkstra(int vertex); void reinitDistance(); void printAdjacentMatrix(); void printPathInfo(int vertexIn) {}; int getNumOfPathsOfOneVertex(int vertex); public: Graph_DG() {}; ~Graph_DG(); int getTotalNumOfPaths(); }; Graph_DG::~Graph_DG() { delete[] m_distance; for (int i = 0; i < this->m_vertexNum; i++) { delete this->m_adjacentMatrix[i]; } delete m_adjacentMatrix; } void Graph_DG::generateGraphDat() { int m_vertexNum; int m_edgeNum = 0; int vertexIn, vertexOut; vector<int> vertexs; cin >> m_vertexNum >> this->m_vertexLondon >> this->m_vertexParis; for (int i = 1; i <= m_vertexNum - 1; i++) { cin >> vertexIn >> vertexOut; vertexs.push_back(vertexIn); vertexs.push_back(vertexOut); m_edgeNum += 2; } ofstream out; out.open("graph.dat"); out << m_vertexNum << " " << m_edgeNum << endl; for (unsigned int i = 0; i < vertexs.size() - 1; i += 2) { out << vertexs[i] << " " << vertexs[i + 1] << " " << 1 << endl; out << vertexs[i + 1] << " " << vertexs[i] << " " << 1 << endl; } out.close(); } bool Graph_DG::check_edgeNum_value(int vertexIn, int vertexOut, int weight) { if (vertexIn < 1 || vertexOut < 1 || vertexIn > m_vertexNum || vertexOut > m_vertexNum || weight < 0) { return false; } return true; } void Graph_DG::reinitDistance() { delete[] m_distance; m_distance = new Distance[this->m_vertexNum]; for (int i = 0; i < this->m_vertexNum; i++) { m_distance[i].value = 0; } } void Graph_DG::createGraph() { int vertexIn; int vertexOut; int weight; ifstream ifp("graph.dat"); ifp >> this->m_vertexNum >> this->m_edgeNum; // allocate space for m_adjacentMatrix and m_distance m_adjacentMatrix = new int*[this->m_vertexNum]; m_distance = new Distance[this->m_vertexNum]; for (int i = 0; i < this->m_vertexNum; i++) { m_adjacentMatrix[i] = new int[this->m_vertexNum]; for (int k = 0; k < this->m_vertexNum; k++) { // initialize each element of adjacent matrix m_adjacentMatrix[i][k] = max_weight; } } for (int i = 0; i < this->m_vertexNum; i++) { m_adjacentMatrix[i][i] = 0; m_distance[i].value = 0; } for (int i = 0; i < this->m_edgeNum; i++) { ifp >> vertexIn >> vertexOut >> weight; m_vertexInSet.insert(vertexIn); m_vertexOutSet.insert(vertexOut); #ifdef UNIT_TEST cout << "V" << vertexIn << " -- " << weight << " --> V" << vertexOut << endl; #endif // assign weight value for vertexIn to vertexOut m_adjacentMatrix[vertexIn - 1][vertexOut - 1] = weight; // add the following line for undirected graph // m_adjacentMatrix[vertexOut-1][vertexIn-1] = weight; } ifp.close(); } void Graph_DG::printAdjacentMatrix() { cout << "Graph's adjacent matrix is " << endl; int row = 0; int col = 0; // start to print adjacent matrix for (int row = 0; row < this->m_vertexNum; row++) { for (int col = 0; col < this->m_vertexNum; col++) { if (max_weight == m_adjacentMatrix[row][col]) { cout << "∞" << " "; } else { cout << setw(2) << m_adjacentMatrix[row][col] << " "; } } cout << endl; } } string Graph_DG::convertInt2String(int n) { string s; stringstream os; os << n; os >> s; return s; } void Graph_DG::Dijkstra(int vertex) { // Firstly, initialize distance array for (int vertexIdx = 0; vertexIdx < this->m_vertexNum; vertexIdx++) { // set the current path m_distance[vertexIdx].path = "V" + convertInt2String(vertex) + " --> V" + convertInt2String(vertexIdx + 1); m_distance[vertexIdx].value = m_adjacentMatrix[vertex - 1][vertexIdx]; m_distance[vertexIdx].pathInfo.push_back(vertex); m_distance[vertexIdx].pathInfo.push_back(vertexIdx + 1); } // calculate the shortest distance from vertex to other vertex (this->m_vertexNum-1) for (int m_vertexNum = 1; m_vertexNum < this->m_vertexNum; m_vertexNum++) { int tmpVertex = 0; // save the minimum vertex index in array m_distance[] int min_value = max_weight; // save the minimum value for (int vertexIdx = 0; vertexIdx < this->m_vertexNum; vertexIdx++) { if (!m_distance[vertexIdx].visit && m_distance[vertexIdx].value < min_value) { min_value = m_distance[vertexIdx].value; tmpVertex = vertexIdx; } } // add tmpVertex to shortest distance path information m_distance[tmpVertex].visit = true; for (int vertexIdx = 0; vertexIdx < this->m_vertexNum; vertexIdx++) { // the condition m_adjacentMatrix[tmpVertex][i]!=max_weigh is required if (!m_distance[vertexIdx].visit && m_adjacentMatrix[tmpVertex][vertexIdx] != max_weight && (m_distance[tmpVertex].value + m_adjacentMatrix[tmpVertex][vertexIdx]) < m_distance[vertexIdx].value) { //if new edge could impact other vertexs which are not visited, update its distance path information m_distance[vertexIdx].value = m_distance[tmpVertex].value + m_adjacentMatrix[tmpVertex][vertexIdx]; m_distance[vertexIdx].path = m_distance[tmpVertex].path + " --> V" + convertInt2String(vertexIdx + 1); m_distance[vertexIdx].pathInfo = m_distance[tmpVertex].pathInfo; m_distance[vertexIdx].pathInfo.push_back(vertexIdx + 1); } } } } int Graph_DG::getNumOfPathsOfOneVertex(int vertex) { int numOfPaths = 0; bool foundLondonTown; bool foundParisTown; for (int i = 0; i != this->m_vertexNum; i++) { foundLondonTown = false; foundParisTown = false; if (m_distance[i].value > 0 && m_distance[i].value != max_weight) { int size = m_distance[i].pathInfo.size(); for(int j=0; j<size; j++) { if (m_distance[i].pathInfo[j] == this->m_vertexLondon) { foundLondonTown = true; } else if (m_distance[i].pathInfo[j] == this->m_vertexParis && true == foundLondonTown) { foundParisTown = true; } } if (false == foundParisTown) { numOfPaths++; #ifdef PRINT_PATH_INFO for (int j = 0; j < size - 1; j++) { cout << m_distance[i].pathInfo[j] << " -> "; } cout << m_distance[i].pathInfo[size-1] << endl; #endif } } } return numOfPaths; } int Graph_DG::getTotalNumOfPaths() { generateGraphDat(); // input data createGraph(); set<int>::iterator iter; int numOfPaths = 0; for (iter = m_vertexInSet.begin(); iter != m_vertexInSet.end(); iter++) { Dijkstra(*iter); numOfPaths += getNumOfPathsOfOneVertex(*iter); reinitDistance(); // re-initialize distance information } return numOfPaths; } int main() { Graph_DG graph; cout << graph.getTotalNumOfPaths() << endl; return 0; }