C++筆試題 奇妙旅行
阿新 • • 發佈:2018-11-02
奇妙旅行
描述
小熊住在由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;
}