题目大意
给出一个有NNN个顶点MMM条边的有向图,对于一条边长度为lenlenlen的边有两种走法。
1、如果aaa和bbb可以互达,则走过这条边的时间为lenlenlen
2、如果aaa和bbb不可以互达,则走过这条边的时间为2∗len2*len2∗len
现在给出一个KKK,问,从顶点111到顶点NNN,满足第二种走法不超过KKK次的最短时间是多少。
题目解析
首先,用FloydFloydFloyd求出两点间是否互达。
然后就是SPFASPFASPFA,对于一个点XXX,设它到达的点为YYY。
易得出:
1、若XXX和YYY可以互达,则F[Y][j]=F[X][j]+a[X][Y](j=0F[Y][j]=F[X][j]+a[X][Y](j=0F[Y][j]=F[X][j]+a[X][Y](j=0 ~ k)k)k)
2、若XXX和YYY不可以互达,则F[Y][j+1]=F[X][j]+a[X][Y]∗2(j=0F[Y][j+1]=F[X][j]+a[X][Y]*2(j=0F[Y][j+1]=F[X][j]+a[X][Y]∗2(j=0 ~k−1)k-1)k−1)
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,k,ans=2147483647;
int a[105][105],f[105][11];
bool vis[105],ff[105][105];
queue<int> q;
int main()
{
cin>>n>>m>>k;
memset(ff,0x3f,sizeof(ff));
for(int i=1,u,v,w;i<=m;i++)
{
cin>>u>>v>>w;
if(a[u][v]==0) a[u][v]=w;
else a[u][v]=min(a[u][v],w);
ff[u][v]=w;
}
for(int l=1;l<=n;l++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j&&j!=l&&i!=l&&ff[i][l]+ff[l][j]<ff[i][j])
ff[i][j]=ff[i][l]+ff[l][j];
q.push(1);
memset(f,0x3f,sizeof(f));
f[1][0]=0;
int u,v;
while(!q.empty())
{
u=q.front();q.pop();
vis[u]=0;
for(int j=1;j<=n;j++)
if(a[u][j]!=0)
{
if(ff[j][u]==0)
{
for(int l=0;l<k;l++)
if(f[u][l]+a[u][j]*2<f[j][l+1])
{
f[j][l+1]=f[u][l]+a[u][j]*2;
if(!vis[j])
{
vis[j]=1;
q.push(j);
}
}
}
else
{
for(int l=0;l<=k;l++)
if(f[u][l]+a[u][j]<f[j][l])
{
f[j][l]=f[u][l]+a[u][j];
if(!vis[j])
{
vis[j]=1;
q.push(j);
}
}
}
}
}
for(int i=0;i<=k;i++)
ans=min(ans,f[n][i]);
if(ans==f[0][0]) cout<<-1;
else cout<<ans;
}