一上来想到拓扑分层最短路,但需要多源最短路。。
这题考查的是对dij的理解
dij只能跑最短路每次都找极值点进行一次拓展,同时不能有负边权
所以一次需要确定 两个值都确定的一个点所以扩展的条件有两个,一个是最短路不被更新,一个是保护的点不再更新
所以就相当于在保护的点中选一个更新
spfa不能维护两个值。。
码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define N 3005
#define M 70005
int tot,hou[M],xia[N],zhong[M],v[M],d[N],jk[N],i,j,n,rd[N],m,a,b,c;
bool vis[N];
queue<int>js[N];
void jia(int a,int b,int c)
{
++tot,hou[tot]=xia[a],xia[a]=tot,zhong[tot]=b,v[tot]=c;
}
void dij()
{
for(i=2;i<=n;i++)d[i]=1000000007;
for(i=1;i<=n;i++)
{
int o=0,minn=1000000007;
for(j=1;j<=n;j++)
if(minn>max(d[j],jk[j])&&vis[j]==0&&rd[j]==0)
{
minn=max(d[j],jk[j]);
o=j;
}
if(o==0)break;
vis[o]=1;
while(!js[o].empty())
{
int nd=js[o].front();
js[o].pop();
if(vis[nd]==1)continue;
jk[nd]=max(jk[nd],minn);
rd[nd]--;
}
for(j=xia[o];j!=-1;j=hou[j])
{
int nd=zhong[j];
if(vis[nd]==1)continue;
d[nd]=min(d[nd],minn+v[j]);
}
}
}
int main()
{
memset(xia,-1,sizeof(xia));
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
jia(a,b,c);
}
for(i=1;i<=n;i++)
{
scanf("%d",&rd[i]);
for(j=1;j<=rd[i];j++)
{
scanf("%d",&b);
js[b].push(i);
}
}
dij();
printf("%d",max(d[n],jk[n]));
}