P6833 [Cnoi2020]雷雨

枚举三条路径重合点,跑dij。预处理出三个点到每个点的最短路。因为事无向边,所以就事每个点到这三个点的最短路。
\(O(nm\log (nm))\)
另外,我的点拆边光荣的挂掉了。
不过可以方格dij。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int cnt=0,ans=0x3f3f3f3f3f3f3f3f;
const int maxn=1e3+5;
int n,m,a,b,c;
int W[maxn][maxn];
int dis[maxn][maxn],adis[maxn][maxn];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
struct node{
    int x,y,w;
    node(){}
    node(int a,int b,int c):x(a),y(b),w(c){}
    bool operator <(const node &b)const{return w>b.w;}
};
void dij(int x,int y){//方格最短路,spfa的噩梦
	memset(dis,0x3f3f3f3f,sizeof(dis));
	priority_queue<node> q;
    q.push((node){x,y,W[x][y]});
    dis[x][y]=W[x][y];
    while(!q.empty()){
        int nx=q.top().x,ny=q.top().y,d=q.top().w;
        q.pop();
        if(d!=dis[nx][ny])continue;
        for(int i=0;i<4;i++){
            int gx=nx+dx[i],gy=ny+dy[i];
            if(gx<1||gx>n||gy<1||gy>m)continue;
            if(dis[gx][gy]>dis[nx][ny]+W[gx][gy]){
                dis[gx][gy]=dis[nx][ny]+W[gx][gy];
                q.push((node){gx,gy,dis[gx][gy]});
            }
        }
    }
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)adis[i][j]+=dis[i][j];
}
signed main(){
	cin>>n>>m>>a>>b>>c;
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>W[i][j];
	dij(1,a),dij(n,b),dij(n,c);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			ans=min(ans,adis[i][j]-2*W[i][j]);
        }
    }
    cout<<ans;
    return 0;
}
上一篇:如何实现安全空运?


下一篇:组合框CComboBox响应函数