You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
4.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
#pragma region SPFA算法模板
// 最短路径——SPFA算法
// 最大值
// https://blog.csdn.net/jiange_zh/article/details/50198097
/**
如果我们想要将某个数组清零我们通常会使用memset(a,0,sizeof(a)),方便又高效,但是当我们想将某个数组全部赋值为无穷大时,
就不能使用memset函数而得自己写循环了因为memset是按字节操作的它能够对数组清零是因为0的每个字节都是0一般我们只有赋值为-1
和0的时候才使用它。现在好了如果我们将无穷大设为0x3f3f3f3f那么奇迹就发生了0x3f3f3f3f的每个字节都是0x3f所以要把一段
内存全部置为无穷大我们只需要memset(a,0x3f,sizeof(a))。所以在通常的场合下0x3f3f3f3f真的是一个非常棒的选择
*/
const int INF = 0x3f3f3f3f;
// https://www.cnblogs.com/xzxl/p/7246918.html
int matrix[100][100]; //邻接矩阵
bool visited[100]; //标记数组
int dist[100]; //源点到顶点i的最短距离
int path[100]; //记录最短路的路径
int enqueue_num[100]; //记录入队次数
int vertex_num; //顶点数
int edge_num; //边数
int source; //源点
bool SPFA() {
memset(visited, 0, sizeof(visited));
memset(enqueue_num, 0, sizeof(enqueue_num));
for (int i = 1; i <= vertex_num; i++) {
dist[i] = INF;
path[i] = source;
}
queue<int> Q;
Q.push(source);
dist[source] = 0;
visited[source] = 1;
enqueue_num[source]++;
while (!Q.empty()) {
int u = Q.front();
Q.pop();
visited[u] = 0;
for (int v = 1; v <= vertex_num; v++) {
if (matrix[u][v] != INF) //u与v直接邻接
{
if (dist[u] + matrix[u][v] < dist[v]) {
dist[v] = dist[u] + matrix[u][v];
path[v] = u;
if (!visited[v]) {
Q.push(v);
enqueue_num[v]++;
if (enqueue_num[v] >= vertex_num)
return false;
visited[v] = 1;
}
}
}
}
}
return true;
}
void Print() {
for (int i = 1; i <= vertex_num; i++) {
if (i != source) {
int p = i;
stack<int> s;
cout << "顶点 " << source << " 到顶点 " << p << " 的最短路径是: ";
while (source != p) //路径顺序是逆向的,所以先保存到栈
{
s.push(p);
p = path[p];
}
cout << source;
while (!s.empty()) //依次从栈中取出的才是正序路径
{
cout << "--" << s.top();
s.pop();
}
cout << " 最短路径长度是:" << dist[i] << endl;
}
}
}
#pragma endregion SPFA算法模板
int main() {
//录入参数文件
freopen("../1411.txt", "r", stdin);
int n;
// 奶牛数,牧场数,牧场间道路数
cin >> n >> vertex_num >> edge_num;
//每个牧场的奶牛数量
vector<int> naiNiuCountArr(vertex_num + 1); //这个容器开始时有 vertex_num + 1 个元素,它们的默认初始值都为 0。
for (int i = 1; i <= n; ++i) {
int d;
cin >> d;
naiNiuCountArr[d]++;
}
//初始为两个节点之间为无穷大
for (int i = 1; i <= vertex_num; i++)
for (int j = 1; j <= vertex_num; j++)
matrix[i][j] = INF; //初始化matrix数组
//读入edge_num条边的信息
for (int i = 1; i <= edge_num; ++i) {
int a, b, c;
cin >> a >> b >> c;
matrix[a][b] = c; //双向,表示是无向图
matrix[b][a] = c; //双向,表示是无向图
}
//遍历每一个顶点,假设将糖放在这个顶点上
int minPath = INF;
int point_vertex_num;
for (int i = 1; i <= vertex_num; ++i) {
//每个顶点都算一次到各个其它顶点的距离
source = i;
SPFA();
//Print();
//假设从source节点出发的话那么需要所有奶牛共同加在一起走的最小路径和
int allPath = 0;
for (int j = 1; j <= vertex_num; j++) {
allPath += dist[j] * naiNiuCountArr[j];
}
//挑出最少的那个节点路径和
if (minPath > allPath) {
minPath = allPath;
//记录是哪个节点时发生了这个变化
point_vertex_num = source;
}
}
// cout << minPath << " " << point_vertex_num << endl;
cout << minPath << endl;
//关闭文件
fclose(stdin);
return 0;
}