JZOJ 1403. 渡河【spfa】


題目:

傳送門


題意:

給出一張地圖,當我們從陸地走向河流時我們需要花費一點代價,詢問圖中的kk個點到地圖邊界最小代價是多少


分析:

我們將所有邊界的點放入SPFASPFA的隊列中,然後由每個邊界點向內拓展,求出邊界到每個點的最小代價,之後再O(1)O(1)回答


代碼:

#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
#define LL long long
using namespace std;
int dx[8]={0,1,1,1,0,-1,-1,-1},dy[8]={-1,-1,0,1,1,1,0,-1};
int t[1005][1005];
int n,m;
struct qwq{
	int x,y;
};
int dis[1005][1005],tf[1005][1005];
void spfa()
{
	queue<qwq> q;
	for(int i=1;i<=n;i++)
	{
		dis[i][1]=dis[i][n]=dis[1][i]=dis[n][i]=0;
		tf[i][1]=tf[i][n]=tf[1][i]=tf[n][i]=1;
		q.push((qwq){i,1});q.push((qwq){i,n});
		q.push((qwq){1,i});q.push((qwq){n,i});
	}
	while(q.size())
	{
		int x=q.front().x,y=q.front().y;tf[x][y]=0;
		q.pop();
		for(int i=0;i<8;i++)
		{
			int vx=x+dx[i],vy=y+dy[i];
			if(vx<1||vx>n||vy<1||vy>n) continue;
			int w=(t[x][y]&&!t[vx][vy]?1:0);
			if(dis[x][y]+w<dis[vx][vy])
			{
				dis[vx][vy]=dis[x][y]+w;
				if(!tf[vx][vy])
				{
					tf[vx][vy]=1;
					q.push((qwq){vx,vy});
				}
			}
		}
	}
	return;
}
int main()
{
	scanf("%d%d",&n,&m);
	char cc;
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=n;j++) {scanf("%c",&cc);while(cc<'0'||cc>'1') scanf("%c",&cc);t[i][j]=cc-'0';}
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=2147483647/3;
	spfa();
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		printf("%d ",dis[x][y]);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章