【洛谷P1491】集合位置
阿新 • • 發佈:2018-12-07
題目大意:求給定的一張無向帶權圖的次短路。
題解:先跑一遍 spfa 求出從起點到終點的最短路,記錄路徑。接著列舉刪邊,並重新跑 spfa,統計最小值即可。
至於為什麼 dp 做法不行,暫時還不清楚。
程式碼如下
#include <bits/stdc++.h> using namespace std; const int maxe=2e4+10; const int maxv=210; const double inf=0x3f3f3f3f; struct node{ int nxt,to; double w; }e[maxe<<1]; int tot=1,head[maxv]; inline void add_edge(int from,int to,double w){ e[++tot]=node{head[from],to,w},head[from]=tot; } int n,m,pre[maxv]; double x[maxv],y[maxv],d[maxv],ans=inf; bool in[maxv]; inline double calc(int a,int b){ return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b])); } void read_and_parse(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%lf%lf",&x[i],&y[i]); for(int i=1,a,b;i<=m;i++){ scanf("%d%d",&a,&b); double c=calc(a,b); add_edge(a,b,c),add_edge(b,a,c); } } queue<int> q; void spfa(int a,int b){ memset(in,0,sizeof(in)); fill(d+1,d+n+1,inf); q.push(1),in[1]=1,d[1]=0; while(q.size()){ int u=q.front();q.pop(),in[u]=0; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to;double w=e[i].w; if((u==a&&v==b)||(v==a&&u==b))continue; if(d[v]>d[u]+w){ d[v]=d[u]+w; if(a==-1&&b==-1)pre[v]=u; if(!in[v])q.push(v),in[v]=1; } } } } void solve(){ spfa(-1,-1); for(int i=n;pre[i];i=pre[i]){ spfa(i,pre[i]); ans=min(ans,d[n]); } if(ans==inf)puts("-1"); else printf("%.2lf\n",ans); } int main(){ read_and_parse(); solve(); return 0; }