最少换站问题

76 阅读1分钟

n个地点间有多条地铁线。求最小换站次数。

思路:给每一条地铁线增加一个汇点(连通该条线上的所有站点)。图建好后就是宽度优先搜索了。

例题:郑轻玲珑杯2130: hipercijevi,类似的题有河南省第八届程序设计-最少换成

下面代码用前向星实现,点实在太多了。里面那个内联函数是为了提高读取速度的。若把read()换为scanf()。速度由600ms变为900ms(仍然可以 )

#include <cstdio> 
#include <iostream>
#include <cstring> 
#include <queue>
#include <algorithm>
using namespace std;
inline int read(){
	int x = 0, f = 1; char ch = getchar();
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x*f;
}
const int maxn = 2000007;
struct Edge{
	int to;
	int next;
}edge[maxn];
int n, k, m, tot, head[101007];
bool vis[101007];
void add(int u, int v) {
	edge[tot].to = v;
	edge[tot].next = head[u];
	head[u] = tot++; 
}
struct Node{
	int v;
	int level;
	Node(int v, int level):v(v),level(level){};
};
void init() {
	tot = 0;
	memset(head, -1, sizeof head); 
}
int bfs(int v0) {
	memset(vis, 0, sizeof vis);
	vis[v0] = true;
	queue<Node> q;
	q.push(Node(v0, 0));
	while(!q.empty()) {
		Node node = q.front();
		q.pop();
		for (int i = head[node.v]; ~i; i = edge[i].next) {
			int v = edge[i].to;
			if (!vis[v]) {
				vis[v] = true;
				q.push(Node(v, node.level + 1));
				if (v == n)
					return (node.level + 1 >> 1) + 1;
			}
		}
	}
	return -1;
}
int main()
{
	int T;
	//scanf("%d", &T);
	T = read();
	while(T--) {
		//scanf("%d%d%d", &n, &k, &m);
		n = read();
		k = read();
		m = read();
		init(); 
		for (int i = 1; i <= m; ++i) { //i从1开始 
			for (int j = 0; j < k; ++j) {
				int tmp;
				//scanf("%d", &tmp);
				tmp = read();
				add(tmp, n + i);
				add(n + i, tmp);
			}
		}
		printf("%d\n", bfs(1));
	}
	
	return 0;
}

\