牛客_BFC_I_Wanna_Go_Home_C++

牛客_BFC_I_Wanna_Go_Home_C++

题目描述

​ The country is facing a terrible civil war----cities in the country are divided into two parts supporting different leaders. As a merchant, Mr. M does not pay attention to politics but he actually knows the severe situation, and your task is to help him reach home as soon as possible. “For the sake of safety,”, said Mr.M, “your route should contain at most 1 road which connects two cities of different camp.” Would you please tell Mr. M at least how long will it take to reach his sweet home?

大意是M先生(后文均以M代替之)现需要从 1 号城市 到 2 号城市;

地图上含至少两个城市,从一个城市到另一个城市存在多条不同长度的路径,路径为双向,

现有两个领导人 1 和 2;

1号城市支持领导人1,2号城市支持领导人2;

其余城市各有支持的领导人,但是仅为1或2

M需要在地图上从1城去到2城,且过程中只能变换支持的领导人一次,即从支持1到支持2

求最短路径

输入描述

The input contains multiple test cases.
The first line of each case is an integer N (2<=N<=600), representing the number of cities in the country.
The second line contains one integer M (0<=M<=10000), which is the number of roads.
The following M lines are the information of the roads. Each line contains three integers A, B and T, which means the road between city A and city B will cost time T. T is in the range of [1,500].
Next part contains N integers, which are either 1 or 2. The i-th integer shows the supporting leader of city i.
To simplify the problem, we assume that Mr. M starts from city 1 and his target is city 2. City 1 always supports leader 1 while city 2 is at the same side of leader 2.
Note that all roads are bidirectional and there is at most 1 road between two cities.
Input is ended with a case of N=0.

第一行为 地图上的 城市数目N

第二行为 地图上的 道路数目M

后M行为 道路的信息,城市 A 和 B 以及 长度 T ∈ [1,500]

后N行仅为1或2,指第 i 个城市支持的领导人

输入以 N = 0 结束

输出描述

For each test case, output one integer representing the minimum time to reach home.
If it is impossible to reach home according to Mr. M’s demands, output -1 instead.

输出最短路径,无则 -1

示例

输入:

2
1
1 2 100
1 2
3
3
1 2 100
1 3 40
2 3 50
1 2 1
5
5
3 1 200
5 3 150
2 5 160
4 3 170
4 2 170
1 2 2 2 1
0

输出:

100
90
540

心路历程

此题我选用 领接矩阵 和 BFC + 优先队列 解答:

邻接矩阵:

5
5
3 1 200
5 3 150
2 5 160
4 3 170
4 2 170
1 2 2 2 1 // 领导人

将如上输入转化为邻接矩阵:

注意 1 3 200 和 3 1 200 本质上是同一个数据

int numberOfRoad;
cin >> numberOfRoad;
        
// 初始化 领接矩阵
vector<vector<int>> roadMap;
for(int i = 0;i < numberOfCity;i++) {
	vector<int> temp(numberOfCity,INT_MAX);
	roadMap.push_back(temp);
}
        
for(int i = 0;i < numberOfRoad;i++) {
	int row;
	int column;
	int cost;
	cin >> row >> column >> cost;
	if(roadMap[row - 1][column - 1] > cost) {
		roadMap[row - 1][column - 1] = cost;
		roadMap[column - 1][row - 1] = cost;
	}
}

// 城市下标 对应的 支持者
vector<int> leaderOfCity;
for(int i = 0;i < numberOfCity;i++) {
	int leader;
	cin >> leader;
	leaderOfCity.push_back(leader);
}

BFC + 优先队列:

先维护一个M先生的状态类,用于BFC:

class Status {
public:
    int cur; // 所在当前城市
    int cost; // 累积走过的路程
    int leader; // 当前城市的leader
};

优先队列对应状态类,操作符重写,根据 cost 排成小顶堆:

bool operator < (const Status& a, const Status& b ){
    
    return a.cost > b.cost; 
}

priority_queue<Status> cityQue; // 优先队列 BFS

由于是使用优先队列,故第一个满足条件的路径,必定是最短路径

例子如图:
在这里插入图片描述

  1. 首先遍历 邻接矩阵 第1行
  2. 发现有道路并且领导人未更换则,更新状态:置当前城市为 i、置累积走过路程,置领导人,随后 全部入队
  3. 将队中元素弹出,用集合设置其已遍历
  4. 遍历所在城市即第 i 行,发现有道路并且领导人未更换则更新状态入队
  5. 重复 步骤 3 4 直到到达城市2 或者队列为空为止
完整代码:
#include <iostream>
#include <vector>
#include <set>
#include <queue>
#include <limits.h>
using namespace std;

class Status {
public:
    int cur;
    int cost;
    int leader;
};

bool operator < (const Status& a, const Status& b ){
    
    return a.cost > b.cost; 
}

int main(void) {
    
    int numberOfCity;
    
    
    while(cin >> numberOfCity) {
        if(numberOfCity == 0) {
            break;
        }
        
        int numberOfRoad;
        cin >> numberOfRoad;
        
        
        // 初始化 领接矩阵
        vector<vector<int>> roadMap;
        for(int i = 0;i < numberOfCity;i++) {
            vector<int> temp(numberOfCity,INT_MAX);
            roadMap.push_back(temp);
        }
        
        for(int i = 0;i < numberOfRoad;i++) {
            int row;
            int column;
            int cost;
            cin >> row >> column >> cost;
            if(roadMap[row - 1][column - 1] > cost) {
                roadMap[row - 1][column - 1] = cost;
                roadMap[column - 1][row - 1] = cost;
            }
        }
        
        
        // 城市下标 对应的 支持者
        vector<int> leaderOfCity;
        for(int i = 0;i < numberOfCity;i++) {
            int leader;
            cin >> leader;
            leaderOfCity.push_back(leader);
        }
        
        set<int> citySet; // 已经访问过的城市
        priority_queue<Status> cityQue; // 优先队列 BFS
        int result = INT_MAX;
        
        
        Status status;
        status.cur = 0;
        status.leader = 1;
        status.cost = 0;
        cityQue.push(status);
        
        int cost = 0;
        while(!cityQue.empty()) {
            Status curSta = cityQue.top();
            cityQue.pop();
            citySet.insert(curSta.cur);
            if(curSta.cur == 1) {
                result = curSta.cost;
                break;
            }

            for(int i = 0;i < numberOfCity;i++) {
                if(roadMap[curSta.cur][i] != INT_MAX 
                   && curSta.leader <= leaderOfCity[i] 
                   && (citySet.find(i) == citySet.end())) {
                    Status status;
                    status.cur = i;
                    status.cost = curSta.cost + roadMap[curSta.cur][i];
                    status.leader = leaderOfCity[i];
                    cityQue.push(status);
                }
            }
            
        }
        
        result = (result == INT_MAX)?-1:result;
        cout << result;
    }
    
    return 0;
}
发布了51 篇原创文章 · 获赞 27 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_39446719/article/details/91909940