听说只能用Dijkstra做
我已经不能分辨DJ和SPFA了
存下每个点的最小到达时间f[i],最晚开放时间g[i],之后用max(f[i],g[i])去增广。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (int j=k;j<=l;++j)
#define red(j,k,l) for (int j=k;j>=l;--j)
#define N 3005
#define M 70005
#define NN 9000005
#define LL long long
#define max(k,l) (((k)>(l))?(k):(l))
using namespace std;
int n,m,cnt,Cnt,to[M],ne[M],st[N],sm[M],To[NN],Ne[NN],St[N];
int h[N],used[N];
LL g[N],f[N];
void add(int k,int l,int poi){
to[++cnt]=l;
sm[cnt]=poi;
ne[cnt]=st[k];
st[k]=cnt;
}
void Add(int k,int l){
To[++Cnt]=l;
Ne[Cnt]=St[k];
St[k]=Cnt;
}
void D(){
//g最早进入 f最短路 h剩余限制
rep(i,1,n) g[i]=(h[i]==0)?0LL:-1LL,used[i]=0,f[i]=-1LL;
f[1]=0LL;
while (1){
int mn=0;
rep(i,1,n) if (used[i]==0&&h[i]==0&&min(f[i],g[i])>=0LL)
mn=(max(f[mn],g[mn])>max(f[i],g[i])||mn==0)?i:mn;
if (mn==0) return;
used[mn]=1;
for (int i=St[mn];i;i=Ne[i])
h[To[i]]--,g[To[i]]=max(max(g[To[i]],f[mn]),g[mn]);
for (int i=st[mn];i;i=ne[i])
if (f[to[i]]==-1LL||f[to[i]]>max(f[mn],g[mn])+sm[i]){
f[to[i]]=max(f[mn],g[mn])+sm[i];
}
}
}
int main(){
scanf("%d%d",&n,&m);
rep(i,1,m){
int k,l,p;
scanf("%d%d%d",&k,&l,&p);
add(k,l,p);
}
rep(i,1,n){
int k,l;scanf("%d",&k);
rep(j,1,k) scanf("%d",&l),Add(l,i);
h[i]=k;
}
D();
printf("%lld\n",max(f[n],g[n]));
system("pause");
}