luogu1613 跑路

题目大意

  一个有向图有起点和终点的有向图,你一次可以走过2^k条边,问从起点到终点所需要走的最小次数。k<=31。

思路

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX_NODE = 55, MAX_DIGIT = 40, INF = 0x3f3f3f3f;
bool Reachable[MAX_NODE][MAX_NODE][MAX_DIGIT];
int Edges[MAX_NODE][MAX_NODE], Dist[MAX_NODE];
int TotNode, TotEdge;

void B_GetReachable()
{
	for (int k = 1; k <= 31; k++)
		for (int u = 1; u <= TotNode; u++)
			for (int v = 1; v <= TotNode; v++)
				for (int mid = 1; mid <= TotNode; mid++)
					Reachable[u][v][k] |= (Reachable[u][mid][k - 1] && Reachable[mid][v][k - 1]);
}

void GetEdge()
{
	memset(Edges, INF, sizeof(Edges));
	for (int k = 0; k <= 31; k++)
		for (int u = 1; u <= TotNode; u++)
			for (int v = 1; v <= TotNode; v++)
				if (Reachable[u][v][k])
					Edges[u][v] = 1;
}

void Bellman_Ford()
{
	memset(Dist, INF, sizeof(Dist));
	Dist[1] = 0;
	for (int k = 1; k <= TotNode; k++)
		for (int u = 1; u <= TotNode; u++)
			for (int v = 1; v <= TotNode; v++)
				Dist[v] = min(Dist[v], Dist[u] + Edges[u][v]);
}

int main()
{
	scanf("%d%d", &TotNode, &TotEdge);
	for (int e = 1; e <= TotEdge; e++)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		Reachable[u][v][0] = true;
	}
	B_GetReachable();
	GetEdge();
	Bellman_Ford();
	printf("%d
", Dist[TotNode]);
	return 0;
}

  

原文地址:https://www.cnblogs.com/headboy2002/p/9384276.html