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;
}
\