洛谷【P1629】邮递员送信(正反最短路径)

题目链接:https://www.luogu.com.cn/problem/P1629
这道题要求节点1到其他节点的来回的最短路径,又由于道路是单向的,所以不仅要求节点1到其他点的最短路径,还要求其他节点到节点1的最短路径,如果运行n次求最短路径会超时,于是求其他节点到节点1的最短路径时,将矩阵转置,从节点1再求一遍最短路径。

#include
#include
#include
#include
using namespace std;
const int N = 1e3 + 10;
const int M = 1e5 + 10;
int a[N][N],d[N],vis[N];
int n,m;
struct Node {
	int u,d;
	bool operator < (const Node& b) const {
		return d > b.d;
	}
};
void Dijkstra(int s)// 迪杰斯特拉堆优化
{
	memset(d,0x3f,sizeof(d));
	memset(vis,0,sizeof(vis));
	priority_queue q;
	d[s] = 0;
	q.push((Node){s,0});
	while(!q.empty()) {
		Node head = q.top();q.pop();
		int u = head.u;
		if(vis[u]) continue;
		vis[u] = 1;
		for(int v = 1; v <= n; v++)
			if(!vis[v] && d[v] > d[u] + a[u][v]) {
				d[v] = d[u] + a[u][v];
				q.push((Node){v,d[v]});
			}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	int u,v,w;
	memset(a,0x3f,sizeof(a));
	for(int i = 0; i < m; i++) {
		scanf("%d%d%d",&u,&v,&w);
		a[u][v] = min(a[u][v],w);// 注意这个坑
	}
	Dijkstra(1);
	int ans = 0;
	for(int i = 2; i <= n; i++)
		ans += d[i];
	for(int i = 1; i <= n; i++)// 矩阵转置
		for(int j = 1; j < i; j++)
			swap(a[i][j],a[j][i]);
	Dijkstra(1);
	for(int i = 2; i <= n; i++)
		ans += d[i];
	printf("%d\n",ans);
	return 0;
}

你可能感兴趣的:(算法)