Age of Moyu
Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2851 Accepted Submission(s): 876
Problem Description
Mr.Quin love fishes so much and Mr.Quin’s city has a nautical system,consisiting of N ports and M shipping lines. The ports are numbered 1 to N. Each line is occupied by a Weitian. Each Weitian has an identification number.
The i-th (1≤i≤M) line connects port Ai and Bi (Ai≠Bi) bidirectionally, and occupied by Ci Weitian (At most one line between two ports).
When Mr.Quin only uses lines that are occupied by the same Weitian, the cost is 1 XiangXiangJi. Whenever Mr.Quin changes to a line that is occupied by a different Weitian from the current line, Mr.Quin is charged an additional cost of 1 XiangXiangJi. In a case where Mr.Quin changed from some Weitian A's line to another Weitian's line changes to Weitian A's line again, the additional cost is incurred again.
Mr.Quin is now at port 1 and wants to travel to port N where live many fishes. Find the minimum required XiangXiangJi (If Mr.Quin can’t travel to port N, print −1instead)
Input
There might be multiple test cases, no more than 20. You need to read till the end of input.
For each test case,In the first line, two integers N (2≤N≤100000) and M (0≤M≤200000), representing the number of ports and shipping lines in the city.
In the following m lines, each contain three integers, the first and second representing two ends Ai and Bi of a shipping line (1≤Ai,Bi≤N) and the third representing the identification number Ci (1≤Ci≤1000000) of Weitian who occupies this shipping line.
Output
For each test case output the minimum required cost. If Mr.Quin can’t travel to port N, output −1 instead.
Sample Input
3 3
1 2 1
1 3 2
2 3 1
2 0
3 2
1 2 1
2 3 2
Sample Output
1
-1
2
Source
2018 Multi-University Training Contest 7
Recommend
chendu | We have carefully selected several similar problems for you: 6408 6407 6406 6405 6404
【思路】
每条边染色,连续走相同颜色的边不加代价,换颜色代价加一。可以推断出边是没必要重复走的,因此按照一步能到达的所有点分层次走,总体上BFS,遇到同颜色的接着往下DFS即可。有点卡常数,用链式前向星建图吧。
【代码】
//******************************************************************************
// File Name: 1001.cpp
// Author: Shili_Xu
// E-Mail: shili_xu@qq.com
// Created Time: 2018年08月15日 星期三 10时28分59秒
//******************************************************************************
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 5, MAXM = 4e5 + 5, INF = 0x3f3f3f3f;
struct edge {
int to, color, next;
edge() {}
edge(int _to, int _color, int _next) : to(_to), color(_color), next(_next) {}
};
struct node {
int u, cost;
node() {}
node(int _u, int _cost) : u(_u), cost(_cost) {}
};
int n, m, cnt;
edge e[MAXM];
int head[MAXN], dist[MAXN];
bool visited[MAXM];
queue<node> q;
void add_edge(int from, int to, int color)
{
e[cnt] = edge(to, color, head[from]);
head[from] = cnt++;
}
void dfs(int u, int c, int d)
{
dist[u] = min(dist[u], d);
q.push(node(u, d));
for (int i = head[u]; i != -1; i = e[i].next) {
if (visited[i] || e[i].color != c) continue;
visited[i] = visited[i ^ 1] = true;
dfs(e[i].to, c, d);
}
}
int main()
{
while (scanf("%d %d", &n, &m) == 2) {
if (m == 0) {
printf("-1\n");
continue;
}
cnt = 0;
memset(head, 0xff, sizeof(head));
for (int i = 1; i <= m; i++) {
int u, v, c;
scanf("%d %d %d", &u, &v, &c);
add_edge(u, v, c);
add_edge(v, u, c);
}
while (!q.empty()) q.pop();
memset(dist, 0x3f, sizeof(dist));
memset(visited, false, sizeof(visited));
dist[0] = 0;
q.push(node(1, 0));
while (!q.empty()) {
node now = q.front(); q.pop();
for (int i = head[now.u]; i != -1; i = e[i].next) {
if (visited[i]) continue;
visited[i] = visited[i ^ 1] = true;
dfs(e[i].to, e[i].color, now.cost + 1);
}
if (dist[n] != INF) break;
}
if (dist[n] == INF)
printf("-1\n");
else
printf("%d\n", dist[n]);
}
return 0;
}