廉价最短路径(特长生2013)【SPFA】【Floyed】

>Description

给出一张有边权的有向图,问在所有从0到1的最短路中,最少花费的一条路花费为多少


>解题思路

考虑到“顶点最多有100个;边最多有1000条”,可以简单地解决这道题
先用floyed跑出从0到1的最短路是多少(也可以用spfa,不过floyed不会爆而且还比较好打所以用floyed)
然后再用spfa跑最少花费,添加一些条件,判断是否为最短路就行


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 110
#define M 1010
#define LL long long
using namespace std;

queue<int> q;
struct edge
{
	int to, next, c;
} e[M];
int n, m, cnt, h[N], p[N];
LL ans, c[N], d[N][N];
bool mark[N];

void add (int u, int v, int w)
{
	e[++cnt] = (edge){v, h[u], w};
	h[u] = cnt;
}

int main()
{
	freopen ("paths.in", "r", stdin);
	freopen ("paths.out", "w", stdout);
	
	memset (c, 0x7f, sizeof (c));
	memset (p, 0x7f, sizeof (p));
	ans = c[0];
	int u, v, w;
	scanf ("%d%d", &n, &m);
	for (int i = 1; i <= m; i++)
	{
		scanf ("%d%d%d", &u, &v, &w);
		u++, v++;
		add (u, v, w);
		d[u][v] = 1;
	}
	for (int i = 1; i <= n; i++) d[i][i] = 0;
	for (int k = 1; k <= n; k++)
	  for (int i = 1; i <= n; i++)
	    for (int j = 1; j <= n; j++)
	      if (i != j && j != k && i != k)
	        if (d[i][k] != 0 && d[k][j] != 0)
	        {
	        	if (d[i][j] == 0) d[i][j] = d[i][k] + d[k][j];
	        	else d[i][j] = min (d[i][j], d[i][k] + d[k][j]);
			}
	q.push (1);
	mark[1] = 1;
	c[1] = p[1] = 0; //c表示花费,p表示路径长
	while (!q.empty())
	{
		u = q.front();
		q.pop();
		mark[u] = 0;
		for (int i = h[u]; i; i = e[i].next)
		{
			v = e[i].to;
			if (c[u] + (LL)e[i].c > c[v]) continue;
			if (p[u] + 1 > p[v]) continue;
			if (p[v] == p[u] + 1)
			  c[v] = min (c[v], c[u] + (LL)e[i].c);
			else c[v] = c[u] + (LL)e[i].c;
			p[v] = p[u] + 1;
			if (v == 2 && p[v] == d[1][2])
			  ans = min (ans, c[v]);
			if (!mark[v])
			{
				q.push(v);
				mark[v] = 1;
			}
		}
	}
	printf ("%lld", ans);
	return 0;
}
上一篇:【bfs】廉价最短路径(2013特长生 T4)


下一篇:SP 2013 解决方案:Windows Server 2012 R2部署SP2013失败