题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3760
题目大意:
边权全部为1的图上,每条边上有一个字母,求字典序最小的最短路
题目大意:
边权全部为1的图上,每条边上有一个字母,求字典序最小的最短路
算法:
预处理出起点和终点到每个点的最短距离。
如果某点到起点和终点的距离和等于最短路的长度,那么它就有可能是最短路上的点。
这样就方便的把图划分了层次,
在这个层次图上,实质上边权就等同于点权。
在同一层的点中找一个字典序最小的即可。
代码如下:
#include<stdio.h>
#include<string.h>
#define INF 0x3f3f3f3f
int Q[100005],d1[100005],d2[100005],head[100005],hash[100005],S2[100005],S1[100005],E,front,rear,top1,top2;
typedef struct
{
int u,v,c,next;
}
EDGE;
EDGE edge[500000];
void addedge(int u,int v,int c)
{
edge[E].v=v;
edge[E].u=u;
edge[E].c=c;
edge[E].next=head[u];
head[u]=E++;
}
int main()
{
int cas,n,m,i,j,u,v,c,nxt;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
memset(d1,-1,sizeof(d1));
memset(d2,-1,sizeof(d2));
memset(head,-1,sizeof(head));
memset(hash,0,sizeof(hash));
E=0;
while(m--)
{
scanf("%d%d%d",&u,&v,&c);
if(u==v)continue;
addedge(u,v,c);
addedge(v,u,c);
}
front=rear=0;
Q[rear++]=n;
d1[n]=0;
while(front!=rear)
{
u=Q[front++];
front%=100000;
for(i=head[u];i!=-1;i=edge[i].next)
{
if(d1[edge[i].v]==-1)
{
d1[edge[i].v]=d1[u]+1;
Q[rear++]=edge[i].v;
}
rear%=100000;
}
}
printf("%d\n",d1[1]);
top1=0;
d2[1]=0;
S1[top1++]=1;
for(j=0;j<d1[1];j++)
{
c=INF;
top2=0;
while(top1--)
{
u=S1[top1];
hash[u]=0;
for(i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(d2[v]==-1)d2[v]=d2[u]+1;
if((d2[v]==d2[u]+1)&&(d1[v]+d2[v]==d1[1])&&(edge[i].c<=c))
{
c=edge[i].c;
S2[top2++]=i;
}
}
}
top1=0;
while(top2--)
{
i=S2[top2];
if(edge[i].c!=c)break;
if(!hash[edge[i].v])
{
hash[edge[i].v]=1;
S1[top1++]=edge[i].v;
}
}
if(j)putchar(' ');
printf("%d",c);
}
puts("");
}
return 0;
}