HLG 1050 Hot Pursuit II【次短路】
题意: 给出一个 有 n 个节点,m 条边的的有向图,求图中的次短路,如果有超过两条以上的最短路,那么次短路的长度即为最短路的长度。
分析: 可以先求出最短路,并保存路径,从 i 到 j 次短路的构成可以用 i 到 点k的次短路加上k 到j 的最短路构成,而i 到 k 的次短路也是通过同样的方法求出,
因此可以通过枚举不在最短路上的边来依次推出 1 到 2..n 的次短路。
#include<stdio.h> #include<string.h> #include<stdlib.h> #define INF 0x1f1f1f1f int g[1003][1003]; int d[1003]; int ord[1003]; int pre[1003]; int sd[1003]; int sl[1003]; int n; void dijkstra() { int s[1002]={0}; int i,j,u,tmp; d[1]=0; pre[1]=-1; ord[1]=1; for(i=1;i<=n;i++) { tmp=INF; for(j=1;j<=n;j++) if(!s[j]&&d[j]<tmp) { u=j; tmp=d[j]; } s[u]=1; ord[i]=u; for(j=1;j<=n;j++) if(d[u]+g[u][j]<d[j]) { d[j]=d[u]+g[u][j]; pre[j]=u; } } } void sec_dijkstra() { int i,j,tmp; for(i=1;i<=n;i++) { tmp=INF; for(j=1;j<=n;j++) if(j!=pre[i]&&d[j]+g[j][i]<tmp) tmp=d[j]+g[j][i]; sd[i]=tmp; } } void cal() { int i; sl[1]=sd[1]; for(i=2;i<=n;i++) { if(sd[ord[i]]<sl[pre[ord[i]]]+g[pre[ord[i]]][ord[i]]) sl[ord[i]]=sd[ord[i]]; else sl[ord[i]]=sl[pre[ord[i]]]+g[pre[ord[i]]][ord[i]]; } } int main() { freopen("D:data1.in","r",stdin); int i,j,m,a,b,w; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++) for(j=1;j<=n;j++) g[i][j]=INF; for(i=1;i<=n;i++) { scanf("%d",&m); while(m--) { scanf("%d%d",&b,&w); g[i][b]=w; } } for(i=1;i<=n;i++) d[i]=INF; dijkstra(); printf("%d ",d[n]); sec_dijkstra(); cal(); printf("%d\n",sl[n]); } return 0; }