传送门
就是一个另类最短路啊。
利用颜色判断当前节点的最小花费的前驱边中有没有跟当前的边颜色相同的。
如果有这条边费用为0,否则费用为1.
这样跑出来就能ac了。
代码:
#include<bits/stdc++.h>
#define N 500005
#define M 500005
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int n,m,first[N],cnt=0,d[N];
bool vis[N];
struct edge{int v,next,c;}e[M<<1];
inline void add(int u,int v,int c){e[++cnt].v=v,e[cnt].next=first[u],e[cnt].c=c,first[u]=cnt;}
struct heap{int u,v;};
inline bool operator<(heap a,heap b){return a.v==b.v?a.u<b.u:a.v<b.v;}
priority_queue<heap>q;
set<int>col[N*10];
inline void dijkstra(){
for(int i=2;i<=n;++i)d[i]=0x3f3f3f3f,vis[i]=false;
q.push((heap){1,d[1]});
while(!q.empty()){
heap x=q.top();
q.pop();
if(vis[x.u])continue;
vis[x.u]=1;
for(int i=first[x.u];i;i=e[i].next){
int v=e[i].v,w=col[x.u].count(e[i].c)?0:1;
if(d[v]>d[x.u]+w)d[v]=d[x.u]+w,q.push((heap){v,-d[v]}),col[v].clear(),col[v].insert(e[i].c);
else if(d[v]==d[x.u]+w)col[v].insert(e[i].c);
}
}
}
int main(){
n=read(),m=read();
for(int i=1;i<=m;++i){
int u=read(),v=read(),c=read();
add(u,v,c),add(v,u,c);
}
dijkstra();
printf("%d",d[n]==0x3f3f3f3f?-1:d[n]);
return 0;
}