BZOJ1922大陆争霸
思路:带限制的单源最短路
限制每个点的条件有二,路程和最早能进入的时间,那么对两个值一起限制跑最短路,显然想要访问一个点最少满足max(dis,time)
那么每次把相连的点以及所保护的点扔进堆中,用以更新答案,不过值得注意的是,入堆的时候进行判断
Code:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; #define p pair<int,int> int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define maxn 3010 #define maxm 70010 int n,m; struct data{int to,next,w;}edge[maxm]; int l[maxn][maxn],lt[maxn],ll[maxn]; int head[maxn],cnt; int S,T; void add(int u,int v,int w) { cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].w=w; } int dis1[maxn],dis2[maxn]; bool visit[maxn]; priority_queue<p,vector<p>,greater<p> >q; void dijkstra() { memset(dis1,0x3f,sizeof(dis1)); q.push(make_pair(0,S)); dis1[S]=0; while (!q.empty()) { int now=q.top().second; q.pop(); if(visit[now]) continue; visit[now]=1; //printf("%d\n",now); int dis=max(dis1[now],dis2[now]); for (int i=head[now]; i; i=edge[i].next) if (dis+edge[i].w<dis1[edge[i].to]) { dis1[edge[i].to]=dis+edge[i].w; int tmp=max(dis1[edge[i].to],dis2[edge[i].to]); if(!ll[edge[i].to]) q.push(make_pair(tmp,edge[i].to)); } //printf("%d\n",lt[now]); for (int i=1; i<=lt[now]; i++) { int noww=l[now][i]; ll[noww]--; dis2[noww]=max(dis2[noww],dis); if (!ll[noww]) q.push(make_pair(max(dis1[noww],dis2[noww]),noww)); } } } int main() { n=read(),m=read(); for (int i=1; i<=m; i++) { int u=read(),v=read(),w=read(); if (u!=v) add(u,v,w); } for (int i=1; i<=n; i++) { ll[i]=read(); for (int j=1; j<=ll[i]; j++) { int x=read(); l[x][++lt[x]]=i; } } S=1;T=n; dijkstra(); // for (int i=1; i<=n; i++) // printf("%d %d\n",dis1[i],dis2[i]); printf("%d\n",max(dis1[T],dis2[T])); return 0; }