【Luogu P1629】 邮递员送信

题目大意:

一个有向图,(n) 个节点 (m) 条边,求第一个点到各个点的最短路径与各个点到第一个点的最短路径之和。

正文:

单源最短路模板题,求 各个点到第一个点的最短路径 时反着存边即可。

代码:

struct node
{
	int z, to, next;
}e[M], dge[M];
int n, m, tot, toto;
int dis[N], sid[N], head[N], daeh[N];
bool vis[N];
queue <int> que;

void Add(int x, int y, int z)
{
	e[++tot] = (node){z, y, head[x]}, head[x] = tot;
}
void Dda(int x, int y, int z)
{
	dge[++toto] = (node){z, y, daeh[x]}, daeh[x] = toto;
}

int SPFA(int s)
{
	memset(dis, 60, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	for(; !que.empty(); que.pop());
	dis[s] = 0, vis[s] = 1;
	que.push(s);
	for (; !que.empty(); que.pop())
	{
		int u = que.front();vis[u] = 0;
		for (int i = head[u]; i; i = e[i].next)
		{
			int v = e[i].to;
			if(dis[v] > dis[u] + e[i].z)
			{
				dis[v] = dis[u] + e[i].z;
				que.push(v);
				vis[v] = 1;
			}
		}
	}
}
int AFPS(int s)
{
	memset(sid, 60, sizeof(sid));
	memset(vis, 0, sizeof(vis));
	for(; !que.empty(); que.pop());
	sid[s] = 0, vis[s] = 1;
	que.push(s);
	for (; !que.empty(); que.pop())
	{
		int u = que.front();vis[u] = 0;
		for (int i = daeh[u]; i; i = dge[i].next)
		{
			int v = dge[i].to;
			if(sid[v] > sid[u] + e[i].z)
			{
				sid[v] = sid[u] + e[i].z;
				que.push(v);
				vis[v] = 1;
			}
		}
	}
}

int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; i++)
	{
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		Add(u, v, w);
		Dda(v, u, w);
	}
	SPFA(1);
	AFPS(1);
	int ans = 0;
	for (int i = 1; i <= n; i++)
		ans += dis[i] + sid[i];
	printf("%d", ans);
	return 0;
}

原文地址:https://www.cnblogs.com/GJY-JURUO/p/13347981.html