#include
using
namespace
std;
const
int
maxn=2005;
const
int
INF=0x7FFFFFFF;//无穷大
int
pre[maxn];//记录一个前驱
int
dis[maxn];//记录距离
int
path[maxn];//记录路径
bool
vis[maxn];//标记点
int
head[maxn];//存边
int
n,m;
int
tot,cnt;
/*struct node//两种方法建立邻接表存图
{
int v,w,next;
node(){}
node(int v,int w,int next):v(v),w(w),next(next){}
}E[maxn*maxn];
void add(int u,int v,int w)
{
E[tot]=node(v,w,head[u]);
head[u]=tot++;
}*/
struct
node
{
int
v,w,next;
}E[maxn*maxn];
void
add(
int
u,
int
v,
int
w)
{
E[tot].v=v;
E[tot].w=w;
E[tot].next=head[u];
head[u]=tot++;
}
void
init()
{
tot=0;
memset
(vis,
false
,
sizeof
((vis)));
memset
(head,-1,
sizeof
(head));
}
void
spfa(
int
st)
{
for
(
int
i=1;i<=n;i++)
{
vis[i]=
false
;
dis[i]=INF;
}
queue<
int
>q;
q.push(st);
int
now,next;
dis[st]=0;
vis[st]=
true
;
pre[st]=-1;
while
(!q.empty())
{
now=q.front();
q.pop();
vis[now]=
false
;//对于弹出队列的就不需要再进入队列了
for
(
int
i=head[now];i!=-1;i=E[i].next)
{
next=E[i].v;
if
(dis[next]>dis[now]+E[i].w)//类似于三角形两边之和大于第三边,是不是就走距离短的那边了
{
dis[next]=dis[now]+E[i].w;
pre[next]=now;//需要记录一下这个点的前驱,对于输出路径有用
if
(!vis[next])//如果这点不在队列里面,就把他加如队列然后再找,就这样一直找
{
vis[next]=
true
;
q.push(next);
}
}
}
}
}
void
print(
int
x)//递归输出路径,每次找到当前点的前驱就可以了
{
if
(pre[x]==-1)
return
;
print(pre[x]);
path[++cnt]=x;//放在后面是正着存的,输出就是正着输出的
}
int
main()
{
int
T;
scanf
(
"%d"
,&T);
for
(
int
cas=1;cas<=T;cas++)
{
init();
scanf
(
"%d%d"
,&n,&m);
int
u,v,w;
for
(
int
i=1;i<=m;i++)
{
scanf
(
"%d%d%d"
,&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
int
st,en;
scanf
(
"%d%d"
,&st,&en);
spfa(st);
if
(dis[en]==INF)//初始化为INF,那么如果终点距离还是INF,那么就说明没有找到最短路径
{
printf
(
"Case %d : none!\n"
,cas);
printf
(
"\n"
);
continue
;
}
cnt=0;
path[++cnt]=st;
print(en);
printf
(
"Case %d : %d\n"
,cas,dis[en]);
for
(
int
i=1;i<=cnt;i++)
{
if
(i
else
printf
(
"%d\n"
,path[i]);
}
printf
(
"\n"
);
}
return
0;
}
|