BZOJ 2622 深入虎穴 题解
怎么会有这么优秀的脑斧
首先题目把题意写得很清楚了,SPFA不会被卡但我没写,就是求一个次小生成树嘛。
考虑Dijkstra,那么就需要修改一小部分:
我们用dis[0][x],dis[1][x]表示从某一个出口到x这个点的最短路与次短路,在读入出口的时候将出口的dis都设为0,压入优先队列,用次短路更新相邻点的最短路与次短路,最后的dis[1][0]就是我们要的答案。
代码如下:
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define HA 19260817 4 #define ERP(i,a) for(int i=head[(a)];i+1;i=e[i].nxt) 5 #define REP(i,a,b) for(int i=(a),edd=(b);i<=edd;++i) 6 #define DRP(i,a,b) for(int i=(a),edd=(b);i>=edd;--i) 7 using namespace std; 8 const int maxn=1e5+5,maxm=1e6+5,inf=0x7fffffff; 9 10 inline int read(){ 11 char ch=getchar(); 12 int r=0,s=1; 13 while(ch>57||ch<48)s=ch==45?0:s,ch=getchar(); 14 while(ch>=48&&ch<=57)r=r*10+ch-48,ch=getchar(); 15 return s?r:-r; 16 } 17 18 priority_queue< pair< int , int > > q; 19 struct edge{int to,nxt,w;}e[maxm<<1]; 20 int n,m,k,cnt; 21 int esp[maxn],dis[2][maxn],vis[maxn],head[maxn]; 22 23 void add(int u,int v,int w){e[++cnt]=(edge){v,head[u],w},head[u]=cnt;return;} 24 25 void init(){ 26 memset(head,-1,sizeof(head));//初始化,因为洞穴标号是从零开始的 27 n=read(),m=read(),k=read(); 28 for(int i=0;i<n;++i)dis[0][i]=dis[1][i]=inf; 29 for(int i=1,x,y,z;i<=m;++i)x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z); 30 for(int i=1;i<=k;++i)esp[i]=read(),q.push(make_pair(0,esp[i])),dis[1][esp[i]]=dis[0][esp[i]]=0; 31 return; 32 } 33 34 void Dijkstra(){//就是个普通的优先队列优化Dijkstra 35 int x,y,z; 36 while(q.size()){ 37 x=q.top().second,q.pop(); 38 if(vis[x])continue; 39 vis[x]=1; 40 for(int i=head[x];i+1;i=e[i].nxt){ 41 y=e[i].to,z=e[i].w; 42 if(!vis[y]){ 43 if(dis[1][y]>dis[1][x]+z){//更新最短路和次短路 44 if(dis[0][y]>dis[1][x]+z){ 45 dis[1][y]=dis[0][y]; 46 dis[0][y]=dis[1][x]+z; 47 } 48 else dis[1][y]=dis[1][x]+z; 49 q.push(make_pair(-dis[1][y],y)); 50 } 51 } 52 } 53 } 54 return; 55 } 56 57 int main(){ 58 freopen("t.in","r",stdin); 59 init(); 60 Dijkstra(); 61 printf("%d\n",dis[1][0]); 62 return 0; 63 }
亲测比SPFA快1000ms左右