题目描述中 pi,qi 联通应表述为 pi,qi 中存在一条无向边,联通表示的是这两个点间存在且仅存在一条边(个人理解),因为显然你重复表述两次同一对联通也不会改变其只有一条边的现状
这是 AC 代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
const int inf=0x3f3f3f3f;
inline int read()
{
int x=0;int f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return ~f?x:-x;
}
struct point{int x,y;}p[maxn];
long double dist(int x,int y){return sqrt((p[x].x-p[y].x)*(p[x].x-p[y].x)+(p[x].y-p[y].y)*(p[x].y-p[y].y));}
struct node{bool flag;int to,nxt;long double w;}edge[maxn];
int head[maxn],tot=1;
map<pair<int,int>,int> id;
void add(int x,int y,long double w)
{
// if(id.count({x,y})) return;
id[{x,y}]=++tot;
edge[tot].to=y;
edge[tot].w=w;
edge[tot].flag=1;
edge[tot].nxt=head[x];
head[x]=tot;
}
int n,m;
pair<int,long double> dis[maxn];bool vis[maxn];
long double spfa()
{
queue<int> q;
for(int i=1;i<=n;i++) {dis[i]=make_pair(-1,inf);vis[i]=0;}
dis[1]=make_pair(-1,0.0);vis[1]=1;q.push(1);
while(!q.empty())
{
int u=q.front();q.pop();
vis[u]=0;
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(!edge[i].flag) continue;
if(dis[v].second>dis[u].second+edge[i].w)
{
dis[v]=make_pair(u,dis[u].second+edge[i].w);
if(!vis[v]) {vis[v]=1;q.push(v);}
}
}
}
return dis[n].second;
}
vector<int> edge_del;
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++) {p[i].x=read();p[i].y=read();}
for(int i=1,x,y;i<=m;i++)
{
x=read();y=read();
add(x,y,dist(x,y));
add(y,x,dist(x,y));
}
long double Max=spfa();
for(int u=n;~u;) {int v=dis[u].first;if(v>=1&&u>=1) edge_del.push_back(id[{u,v}]);u=v;}
long double ans=inf;
// cout<<edge_del.size()<<endl<<endl;
for(int i:edge_del)
{
edge[i].flag=edge[i^1].flag=0;
ans=min(ans,spfa());
edge[i].flag=edge[i^1].flag=1;
}
ans==inf?puts("-1"):printf("%.2Lf\n",ans);
return 0;
}
这是 WAon #4,#5,#6
#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
const int inf=0x3f3f3f3f;
inline int read()
{
int x=0;int f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return ~f?x:-x;
}
struct point{int x,y;}p[maxn];
long double dist(int x,int y){return sqrt((p[x].x-p[y].x)*(p[x].x-p[y].x)+(p[x].y-p[y].y)*(p[x].y-p[y].y));}
struct node{bool flag;int to,nxt;long double w;}edge[maxn];
int head[maxn],tot=1;
map<pair<int,int>,int> id;
void add(int x,int y,long double w)
{
if(id.count({x,y})) return;
id[{x,y}]=++tot;
edge[tot].to=y;
edge[tot].w=w;
edge[tot].flag=1;
edge[tot].nxt=head[x];
head[x]=tot;
}
int n,m;
pair<int,long double> dis[maxn];bool vis[maxn];
long double spfa()
{
queue<int> q;
for(int i=1;i<=n;i++) {dis[i]=make_pair(-1,inf);vis[i]=0;}
dis[1]=make_pair(-1,0.0);vis[1]=1;q.push(1);
while(!q.empty())
{
int u=q.front();q.pop();
vis[u]=0;
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(!edge[i].flag) continue;
if(dis[v].second>dis[u].second+edge[i].w)
{
dis[v]=make_pair(u,dis[u].second+edge[i].w);
if(!vis[v]) {vis[v]=1;q.push(v);}
}
}
}
return dis[n].second;
}
vector<int> edge_del;
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++) {p[i].x=read();p[i].y=read();}
for(int i=1,x,y;i<=m;i++)
{
x=read();y=read();
add(x,y,dist(x,y));
add(y,x,dist(x,y));
}
long double Max=spfa();
for(int u=n;~u;) {int v=dis[u].first;if(v>=1&&u>=1) edge_del.push_back(id[{u,v}]);u=v;}
long double ans=inf;
// cout<<edge_del.size()<<endl<<endl;
for(int i:edge_del)
{
edge[i].flag=edge[i^1].flag=0;
ans=min(ans,spfa());
edge[i].flag=edge[i^1].flag=1;
}
ans==inf?puts("-1"):printf("%.2Lf\n",ans);
return 0;
}