HDU 6386 - Age of Moyu [2018杭电多校联赛第七场 A](最短路变形)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6386
【题意】
给定一个n个结点m条边的无向图,结点编号为1~n,每条边有一个类型属性,现在要从结点1出发走到结点n,连续地走同种类型的边只会花费1的代价,如果当前边的类型为A,下一步走到了类型为B的边上,就会产生额外的代价,问你最小代价是多少
【输入格式】
多组输入,每组数据的第一行为两个整数n,m(n<=1e5,m<=2e5)接下来m行每行三个整数u,v,c代表结点u,v之间有一条类型为c的无向边(1<=u,v<=n, 1<=c<=1e6)
【输出格式】
对每组数据,输出最小代价,如果无法到达终点则输出-1
【思路】
依然是最短路径,在堆结点中额外增加一项就是到达该点时所走的上一条边的类型,这样如果下一条边的类型和它一样那么可以直接更新最短路,否则要将距离加1之后再更新最短路。还有就是第一次访问到某个点是更新出来的距离不一定就是最短的,所以要让结点重复进队列,直到无法更新最短路为止.
#include<bits/stdc++.h>
using namespace std;
const int inf = 2e9;
const int maxn = 100050;
struct Edge {
int from, to, dist;
Edge(int f, int t, int d) :from(f), to(t), dist(d) {}
};
struct HeapNode {
int d, u, cur;
HeapNode(int dd, int uu,int cc) :d(dd), u(uu), cur(cc) {}
bool operator < (const HeapNode& rhs) const {
return d > rhs.d;
}
};
struct Dijkstra {
int n, m;
vector<Edge> edges;
vector<int> g[maxn];
int d[maxn];
void init(int n) {
this->n = n;
for (int i = 0; i < n; ++i) g[i].clear();
edges.clear();
}
void add(int from, int to, int dist) {
edges.push_back(Edge(from, to, dist));
m = edges.size();
g[from].push_back(m - 1);
}
void dijkstra(int s) {
priority_queue<HeapNode> que;
for (int i = 0; i < n; ++i) d[i] = inf;
d[s] = 0;
que.push(HeapNode(0, s, -1));
while (!que.empty()) {
HeapNode x = que.top();
que.pop();
int u = x.u;
int cur = x.cur;
for (int i = 0; i < g[u].size(); ++i) {
Edge& e = edges[g[u][i]];
if(e.dist==cur){
if(d[e.to]>d[u]){
d[e.to]=d[u];
que.push(HeapNode(d[e.to],e.to,cur));
}
}
else{
if(d[e.to]>d[u]+1){
d[e.to]=d[u]+1;
que.push(HeapNode(d[e.to]+1,e.to,e.dist));
}
}
}
}
}
};
int n, m;
Dijkstra dij;
int main() {
while(scanf("%d%d",&n,&m)==2){
dij.init(n);
for(int i=0;i<m;++i){
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
--u,--v;
dij.add(u,v,c);
dij.add(v,u,c);
}
dij.dijkstra(0);
int ans=dij.d[n-1];
if(ans==inf) puts("-1");
else printf("%d\n",ans);
}
return 0;
}