P1491 集合位置 求次短路
题意:0.0
思路:我们把图建好之后,先跑一遍求出最短路路径,然后再枚举要删除的边
要删除的边自然是最短路径上的边,因为假如不选最短路径上的边,权值是不会变化的
所以,要想求次短路,我们就注意枚举最短边然后更新答案即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e3+10; 4 const double inf=1000000000.0; 5 double x[maxn],y[maxn]; 6 int match[maxn]; 7 int cut[maxn][maxn]; 8 double dis[maxn]; 9 int vis[maxn]; 10 int n,m; 11 double cal(int t1,int t2) 12 { 13 return sqrt((x[t1]-x[t2])*(x[t1]-x[t2])+(y[t1]-y[t2])*(y[t1]-y[t2])); 14 } 15 struct node 16 { 17 int v,nxt; 18 double w; 19 }G[20010]; int head[20010]; int num; 20 void add(int u,int v,double w) 21 { 22 G[++num].v=v;G[num].w=w;G[num].nxt=head[u];head[u]=num; 23 } 24 void SPFA1() 25 { 26 queue<int>q; 27 for(int i=0;i<=n;i++){ 28 dis[i]=inf; 29 vis[i]=0; 30 } 31 q.push(1); 32 vis[1]=1; 33 dis[1]=0.0; 34 while(!q.empty()){ 35 int u=q.front(); 36 q.pop(); 37 vis[u]=0; 38 for(int i=head[u];i;i=G[i].nxt){ 39 int v=G[i].v; 40 double w=G[i].w; 41 if(dis[v]>dis[u]+w){ 42 dis[v]=dis[u]+w; 43 match[v]=u; 44 if(!vis[v]){ 45 q.push(v); 46 vis[v]=1; 47 } 48 } 49 } 50 } 51 } 52 void SPFA2() 53 { 54 queue<int>q; 55 for(int i=0;i<=n;i++){ 56 dis[i]=inf; 57 vis[i]=0; 58 } 59 q.push(1); 60 vis[1]=1; 61 dis[1]=0.0; 62 while(!q.empty()){ 63 int u=q.front(); 64 q.pop(); 65 vis[u]=0; 66 for(int i=head[u];i;i=G[i].nxt){ 67 int v=G[i].v; 68 double w=G[i].w; 69 if(cut[u][v]) continue; 70 if(dis[v]>dis[u]+w){ 71 dis[v]=dis[u]+w; 72 if(!vis[v]){ 73 q.push(v); 74 vis[v]=1; 75 } 76 } 77 } 78 } 79 } 80 int main() 81 { 82 scanf("%d%d",&n,&m); 83 for(int i=1;i<=n;i++){ 84 scanf("%lf%lf",&x[i],&y[i]); 85 } 86 for(int i=1;i<=m;i++){ 87 int u,v; 88 scanf("%d%d",&u,&v); 89 double w=cal(u,v); 90 add(u,v,w); 91 add(v,u,w); 92 } 93 SPFA1(); 94 int now=n; 95 double ans=inf; 96 while(match[now]){ 97 int u=now;int v=match[now]; 98 cut[u][v]=cut[v][u]=1; 99 SPFA2(); 100 cut[u][v]=cut[v][u]=0; 101 ans=min(ans,dis[n]); 102 now=match[now]; 103 } 104 if(ans>=inf) printf("-1\n"); 105 else printf("%.2f\n",ans); 106 return 0; 107 }