一个图n个点,m条边。在一条路上,如果连续路径上的权值相同,那么花费1就可以到达,例1-1-1三条路,四个点,这四个点互通都只花费1.例1-2-1三条路,四个点,从第一个点到第四个点花费为3(权值修改了三次)。
思路:
bfs查询路径,每条路都只走一次。每一个点入队列后,再用dfs把所有与当前路径相同权值的路径加入。本质上是记录依次花费1,2,....步能到达哪里。bfs先查到的一定是从1到n的最短路径。
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,m,cas,ans;
int dis[N],head[N],look[N];
queue<int>q;
struct Edge
{
int u,v,w,next,vis;
}edge[N*4];
void add_edge(int u,int v,int w)
{
edge[cas].u=u;
edge[cas].v=v;
edge[cas].w=w;
edge[cas].next=head[u];
edge[cas].vis=0;
head[u]=cas++;
}
void dfs(int rt,int cl,int num)
{
int i,j;
if(rt==n)
{
ans=num;
return;
}
if(!look[rt])
{
look[rt]=1;
dis[rt]=num;
q.push(rt);
}
for(i=head[rt];i!=-1;i=edge[i].next)
{
if(edge[i].vis)
continue;
if(edge[i].w==cl)
{
edge[i].vis=1;
dfs(edge[i].v,cl,num);
}
}
return;
}
int bfs()
{
int i,j,v;
while(!q.empty())
q.pop();
q.push(1);
dis[1]=0;
look[1]=1;
while(!q.empty())
{
int now=q.front();
q.pop();
for(i=head[now];i!=-1;i=edge[i].next)
{
if(edge[i].vis)
continue;
v=edge[i].v;
edge[i].vis=1;
dfs(v,edge[i].w,dis[now]+1);
if(ans>0)
break;
}
if(ans>0)
break;
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int i,j;
cas=0;
memset(head,-1,sizeof(head));
memset(look,0,sizeof(look));
memset(dis,0x3f3f3f3f,sizeof(dis));
for(i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
}
ans=-1;
ans=bfs();
printf("%d\n",ans);
}
return 0;
}