反向搜索 只要搜一次就行
另外本题不标记 因为传送门会使之前的结果不一定是最优的。增加了空间复杂度。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fp(i,a,b) for(int i=a;i<=b;++i)
#define PII pair<int,int>
const int N=2e3+10;
const int mod=1e9+7;
const double eps=1e-5;
typedef double db;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int n,m;
int dist[N][N];
vector<PII>door[N][N];
bool is_door[N][N];
void bfs()
{
memset(dist,0x3f,sizeof dist);
dist[n][n]=0;
queue<PII>q;
q.push({n,n});
while(q.size())
{
auto t=q.front();
q.pop();
for(int p=0;p<4;p++)
{
int X=dx[p]+t.first,Y=dy[p]+t.second;
if(X<1||X>n||Y<1||Y>n) continue;
if(dist[X][Y]>dist[t.first][t.second]+1)
{
dist[X][Y]=dist[t.first][t.second]+1;
q.push({X,Y});
}
if(is_door[t.first][t.second])//如果当前点可以使用传送门
{
//因为是反向搜图,可以多对一
for(auto s:door[t.first][t.second])
{
//取出里面的点
if(dist[s.first][s.second]>dist[t.first][t.second]+1)
{
dist[s.first][s.second]=dist[t.first][t.second]+1;
q.push({s.first,s.second});
}
}
}
}
}
}
signed main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b,c,d;
cin>>a>>b>>c>>d;
door[a][b].push_back({c,d});
door[c][d].push_back({a,b});
is_door[a][b]=is_door[c][d]=true;
}
bfs();
int sum=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
sum+=dist[i][j];
}
}
cout<<fixed<<setprecision(2)<<1.0*sum/(n*n)<<"\n";
return 0;
}