http://codeforces.com/problemset/problem/230/D
在普通最短路的基础上 每个点在一些时间点是无法到达的 看了题解才懂。。
松驰每个点时 看一下该点在当前用来松弛的这个时间点能否到达 能就直接松驰 不能就找一个最近的合法时间 这样对于每个点 相当于来的时间段不同 则边的权值不同 预处理二分即可
#include <bits/stdc++.h>
using namespace std;
const int N=0x3f3f3f3f;
struct node
{
int v;
int w;
int next;
};
vector <int> pre[100010],nxt[100010];
queue <int> que;
node edge[200010];
int first[100010],dis[100010],book[100010];
int n,m,num;
void addedge(int u,int v,int w)
{
edge[num].v=v;
edge[num].w=w;
edge[num].next=first[u];
first[u]=num++;
}
int gettime(int u,int t)
{
int l,r,mid;
l=0,r=pre[u].size()-1;
while(l<=r)
{
mid=(l+r)/2;
if(pre[u][mid]<t) l=mid+1;
else if(pre[u][mid]>t) r=mid-1;
else return nxt[u][mid];
}
return t;
}
int spfa()
{
int i,u,v,w,res;
memset(dis,0x3f,sizeof(dis));
que.push(1);
dis[1]=gettime(1,0);
book[1]=1;
while(!que.empty())
{
u=que.front();
que.pop();
book[u]=0;
//printf("***%d***\n",u);
for(i=first[u];i!=-1;i=edge[i].next)
{
v=edge[i].v,w=edge[i].w;
if(v==n) res=dis[u]+w;
else res=gettime(v,dis[u]+w);
if(dis[v]>res)
{
dis[v]=res;
if(book[v]==0)
{
que.push(v);
book[v]=1;
}
}
}
}
return dis[n];
}
int main()
{
int i,j,u,v,w,k,p,res;
scanf("%d%d",&n,&m);
memset(first,-1,sizeof(first));
num=0;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
for(i=1;i<=n;i++)
{
scanf("%d",&k);
while(k--)
{
scanf("%d",&w);
pre[i].push_back(w);
nxt[i].push_back(0);
}
sort(pre[i].begin(),pre[i].end());
for(j=pre[i].size()-1,p=-1;j>=0;j--)
{
if(p==-1||pre[i][j]+1!=pre[i][j+1]) nxt[i][j]=pre[i][j]+1;
else nxt[i][j]=p;
p=nxt[i][j];
}
}
res=spfa();
if(res==N) printf("-1\n");
else printf("%d\n",res);
return 0;
}
/*
2 1
1 2 3
0
1 3
*/