P1491 集合位置(次短路)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1491 集合位置(次短路)相关的知识,希望对你有一定的参考价值。
P1491 集合位置(次短路)
第一遍跑dij的时候记录下最短路径的每个点的前驱结点,然后依次删除这些边,再跑最短路得到的就是第二短路,注意特判只有一条最短路的情况。
与P1186类似,应该也可以用线段树+并查集优化。
code
// Problem: P1491 集合位置
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1491
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-07-05 10:36:17
// --------by Herio--------
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=205,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\\n",a[n]);
}
struct node{
int x,y;
}a[N];
int n,m;
struct edge{
int to,nt;
int pre;
double w;
}e[N*N];
int h[N],cnt;
void add(int u,int v,double w){
e[++cnt]={v,h[u],u,w};h[u]=cnt;
e[++cnt]={u,h[v],v,w};h[v]=cnt;
}
double d[N];
int vis[N];
int b[N];
double dij(int p){
priority_queue<pair<double,int> >q;
q.push({0,1});
for(int i=1;i<=n;i++) d[i]=1e18,vis[i]=0;
d[1]=0;
while(!q.empty()){
auto qu=q.top();q.pop();
int u=qu.se;
if(vis[u]) continue;
vis[u]=1;
for(int i=h[u];i;i=e[i].nt){
if(i==p) continue;
int v=e[i].to;double w=e[i].w;
if(!vis[v]&&d[v]>d[u]+w){
d[v]=d[u]+w;
if(!~p) b[v]=i;
q.push({-d[v],v});
}
}
}
return d[n];
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].x,&a[i].y);
}
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
double d=sqrt((a[u].x-a[v].x)*(a[u].x-a[v].x)+(a[u].y-a[v].y)*(a[u].y-a[v].y));
add(u,v,d);
}
dij(-1);
int pos=n;
double ans=1e18;
while(pos!=1){
ans=min(ans,dij(b[pos]));
pos=e[b[pos]].pre;
}
if(ans<1e18) printf("%.2f\\n",ans);
else printf("-1\\n");
return 0;
}
以上是关于P1491 集合位置(次短路)的主要内容,如果未能解决你的问题,请参考以下文章