出处
http://blog.csdn.net/harlow_cheng/article/details/52262956
通过这道题加深了对floyd的理解,通过中间点k去更新与之相连的点。原理讲的很清晰,必须点赞:)
代码做了微调
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct question //用结构体把询问存下来。
{
int x,y,time;
}a[50001];
int n,m,t[201],w[201][201],q; //t数组是各个节点修建好的时间。
void get_ans()
{
int now=1;
t[n+1]=t[n]+10000; //这是防止上溢。
for (int k=0;k<=n;k++) //k从0开始枚举
{
for (int i=1;i<=n;i++) //以k作为中间节点尝试更新任意两点之间的距离。
for (int j=1;j<=n;j++)
if (w[i][j]>w[i][k]+w[k][j])
w[i][j]=w[i][k]+w[k][j];
while (now<=q&&t[k]<=a[now].time&&t[k+1]>a[now].time)
{//如果询问还没结束。且这个节点在所询问的时间内。且k+1这个节点修建的时间超过询问的时间
if (t[a[now].x]>a[now].time||t[a[now].y]>a[now].time)
printf("-1\n");
else //输出依靠前k个节点作为中间节点更新出的任意两点之间的距离
{
if (w[a[now].x][a[now].y]>=w[0][0])
printf("-1\n");
else
printf("%d\n",w[a[now].x][a[now].y]);
}
now++; //看一下下一个询问是否符合要求。
}
if (now>q) //如果询问都输出了则结束。
break;
}
}
int main()
{
memset(w,127/3,sizeof(w));//一开始w数组赋值为一个很大的数字。
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) //输入各个节点修建好的时刻。
scanf("%d",&t[i]);
for (int i=1;i<=m;i++) //输入边权信息。
{
int x, y, z;
scanf("%d%d%d",&x,&y,&z);
x++; y++;
w[x][y]=w[y][x]=z;
}
scanf("%d", &q);
for (int i=1;i<=q;i++) //输入q个询问。
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].time);
a[i].x++;
a[i].y++;
}
get_ans();
return 0;
}