Uva




先倒着BFS,找到每个结点i到重点最短距离d[i],然后直接起点开始BFS,如果有多种走法,选颜色字典序最小的走。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <stack>
#include <queue>
#include <bitset> 
#include <cassert> 

using namespace std;

const int maxn = 100005;
const int maxc = 1000000000;

struct Edge {
	int u, v, c;
	Edge(int u = 0, int v = 0, int c = 0) : u(u), v(v), c(c) {}
};

vector<Edge> edges;
vector<int> G[maxn];

void addEdge(int u, int v, int c)
{
	edges.push_back(Edge(u, v, c));
	int idx = edges.size() - 1;
	G[u].push_back(idx);
}

int n, vis[maxn];
int d[maxn]; // 每个结点i到重点的最短距离d[i]

// 从终点倒着BFS,找到到达n-1的最短路
void revBfs()
{
	memset(vis, 0, sizeof(vis));
	d[n - 1] = 0;
	vis[n - 1] = true; // 访问状态

	queue<int> q;
	q.push(n - 1);
	while (!q.empty()) {
		int v = q.front();
		q.pop();
		for (int i = 0; i < G[v].size(); i++) {
			int e = G[v][i];
			int u = edges[e].v;
			if (!vis[u]) { // 还没有杯访问过
				vis[u] = true;
				d[u] = d[v] + 1;
				q.push(u);
			}
		}
	}
}

vector<int> ans;

// 从起点开始BFS,如果有多种走法,选颜色字典序最小的走
void bfs()
{
	memset(vis, 0, sizeof(vis));
	vis[0] = true;
	ans.clear();

	vector<int> next;
	next.push_back(0);
	for (int i = 0; i < d[0]; i++) {
		int minColor = maxc;
		for (int j = 0; j < next.size(); j++) {
			int u = next[j];
			for (int k = 0; k < G[u].size(); k++) {
				int e = G[u][k];
				int v = edges[e].v;
				if (d[u] == d[v] + 1) {
					minColor = min(minColor, edges[e].c);
				}
			}
		}
		ans.push_back(minColor);
		
		// 再一次BFS
		vector<int> next2;
		for (int j = 0; j < next.size(); j++) {
			int u = next[j];
			for (int k = 0; k < G[u].size(); k++) {
				int e = G[u][k];
				int v = edges[e].v;
				if (d[u] == d[v] + 1 &&
					!vis[v] &&
					edges[e].c == minColor) {
					vis[v] = true;
					next2.push_back(v);
				}
			}
		}
		next = next2;
	}

	printf("%d
", ans.size());
	printf("%d", ans[0]);
	for (int i = 1; i < ans.size(); i++) {
		printf(" %d", ans[i]);
	}
	printf("
");
}

int main()
{
	int u, v, c, m;
	while (scanf("%d%d", &n, &m) == 2) {
		edges.size();
		for (int i = 0; i < n; i++) {
			G[i].clear();
		}
		while (m--) {
			scanf("%d%d%d", &u, &v, &c);
			addEdge(u - 1, v - 1, c);
			addEdge(v - 1, u - 1, c);
		}
		revBfs();
		bfs();
	}

	return 0;
}




原文地址:https://www.cnblogs.com/zhangyaoqi/p/4591547.html