BZOJ2622 深入虎穴(最短路径)
如果对某个点能求出与其相邻的所有点到达出口的最短时间,那么该点的答案就可以在其中取次小值了。
对于dijkstra魔改一下就能做到这个。初始时将所有出口的最短时间设为0并放入堆,记录最短和次短路径,每个点更新后将次短路径入堆。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 100010 #define M 2000010 #define inf 700000000 int n,m,k,p[N],d[N],d2[N],t=0,ans=inf; bool flag[N]; struct data{int to,nxt,len; }edge[M]; struct data2 { int x,d; bool operator <(const data2&a) const { return d>a.d; } }; priority_queue<data2> q; void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;} void dijkstra() { memset(flag,0,sizeof(flag)); for (int i=1;i<=n;i++) { while (!q.empty()&&flag[q.top().x]) q.pop(); if (q.empty()) break; data2 v=q.top();q.pop(); flag[v.x]=1; for (int j=p[v.x];j;j=edge[j].nxt) if (v.d+edge[j].len<d[edge[j].to]) { d2[edge[j].to]=d[edge[j].to]; d[edge[j].to]=v.d+edge[j].len; q.push((data2){edge[j].to,d2[edge[j].to]}); } else if (v.d+edge[j].len<d2[edge[j].to]) { d2[edge[j].to]=v.d+edge[j].len; q.push((data2){edge[j].to,d2[edge[j].to]}); } } } int main() { #ifndef ONLINE_JUDGE freopen("bzoj2622.in","r",stdin); freopen("bzoj2622.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(),k=read(); for (int i=1;i<=m;i++) { int x=read()+1,y=read()+1,z=read(); addedge(x,y,z),addedge(y,x,z); } memset(d,42,sizeof(d));memset(d2,42,sizeof(d2)); for (int i=1;i<=k;i++) { int x=read()+1; d[x]=d2[x]=0;q.push((data2){x,0}); } dijkstra(); cout<<d2[1]; return 0; }