【BZOJ】1726 [Usaco2006 Nov]Roadblocks第二短路
【算法】最短路(spfa) 次短路
【题解】
正反跑两次SPFA,然后枚举每一条边,如果起点到一个端点的最短路+另一个端点到终点的最短路+长度 ≠ 最短路,则和答案比较,保存最小值。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=5010,maxm=100010,inf=0x3f3f3f3f; struct edge{int u,v,w,from;}e[maxm*3]; int n,m,first[maxn],dist[maxn],dis1[maxn],dis2[maxn],tot,q[maxn*3]; bool vis[maxn]; void insert(int u,int v,int w) {tot++;e[tot].u=u;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;} void spfa(int s) { memset(vis,0,sizeof(vis)); memset(dist,0x3f,sizeof(dist)); int l=1,r=1;q[1]=s;dist[s]=0;vis[s]=1; while(l<=r) { int x=q[l++]; for(int i=first[x];i;i=e[i].from) if(dist[x]+e[i].w<dist[e[i].v]) { int y=e[i].v; dist[y]=dist[x]+e[i].w; if(!vis[y]) { q[++r]=y; vis[y]=1; } } vis[x]=0; } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); insert(u,v,w); insert(v,u,w); } spfa(1); for(int i=1;i<=n;i++)dis1[i]=dist[i]; spfa(n); for(int i=1;i<=n;i++)dis2[i]=dist[i]; int ans=inf; for(int i=1;i<=tot;i++) { int x=e[i].u,y=e[i].v; int now=dis1[x]+dis2[y]+e[i].w; if(now>dis1[n]&&now<ans)ans=now; now=dis1[y]+dis2[x]+e[i].w; if(now>dis1[n]&&now<ans)ans=now; } printf("%d",ans); return 0; }
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int maxn=5010,maxm=200010,inf=0x3f3f3f3f; struct edge{int from,u,v,w;}e[maxm]; struct Node{int x,d;}cyc; int n,m,first[maxn],tot,d[maxn],d_[maxn],s,t,anss,ans; priority_queue<Node>q; bool operator <(Node a,Node b) {return a.d>b.d;} void insert(int u,int v,int w) {tot++;e[tot].u=u;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;} void dijkstra(int* d) { for(int i=1;i<=n;i++)d[i]=inf; d[s]=0; cyc.x=s,cyc.d=d[s];q.push(cyc); while(!q.empty()) { cyc=q.top();q.pop(); if(cyc.d!=d[cyc.x])continue; int x=cyc.x; for(int i=first[x];i;i=e[i].from) if(d[e[i].v]>d[x]+e[i].w) { d[e[i].v]=d[x]+e[i].w; cyc.x=e[i].v,cyc.d=d[e[i].v]; q.push(cyc); } } anss=d[t]; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); insert(u,v,w); insert(v,u,w); } s=1;t=n; dijkstra(d); s=n;t=1; dijkstra(d_); int ans=inf; for(int i=1;i<=tot;i++) { if(d[e[i].u]+e[i].w+d_[e[i].v]>anss) ans=min(ans,d[e[i].u]+e[i].w+d_[e[i].v]); } printf("%d",ans); return 0; }