题目大意:s会分裂,然后从s到A的最小的步是多少。
解题思路:先bfs算出A或者S到任何点的距离,然后最求最小生成树,用dij或者prim都可以
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 100+10;
char mp[maxn][maxn];
int cost[maxn][maxn];
int a[maxn][maxn];
int T[maxn][maxn];
int d[4][2]={0,1,0,-1,1,0,-1,0};
struct Point{
int x,y;
Point(){};
Point(int zz,int yy){
x=zz;
y=yy;
}
};
struct Node{
int u,v;
int cost;
}node[maxn*maxn];
bool cmd(Node a,Node b){
return a.cost<b.cost;
}
int pa[maxn];
int find(int x){
if(pa[x]==x) return x;
else return pa[x]=find(pa[x]);
}
void join(int x,int y){
int root=find(x);
int root1=find(y);
if(root!=root1){
pa[root1]=root;
}
}
bool same(int x,int y){
return find(x)==find(y);
}
void bfs(int x,int y){
memset(T,-1,sizeof(T));
queue<Point> q;
while(!q.empty()) q.pop();
q.push(Point(x,y));
T[x][y]=0;
while(!q.empty()){
Point p;
p=q.front();
q.pop();
if(a[p.x][p.y]!=-1){
cost[a[x][y]][a[p.x][p.y]]=T[p.x][p.y];
}
for(int i=0;i<4;i++){
int dx=p.x+d[i][0];
int dy=p.y+d[i][1];
if(mp[dx][dy]=='#' || T[dx][dy]!=-1) continue;
T[dx][dy]=T[p.x][p.y]+1;
q.push(Point(dx,dy));
}
}
}
int dij(int tot){
for(int i=0;i<=tot;i++) pa[i]=i;
int c=0;
for(int i=0;i<tot;i++){
for(int j=0;j<i;j++){
if(cost[i][j]>0){
node[c].u=i;
node[c].v=j;
node[c++].cost=cost[i][j];
}
}
}
sort(node,node+c,cmd);
int sum=0;
for(int i=0;i<c;i++){
int u=node[i].u;
int v=node[i].v;
if(!same(u,v)){
sum+=node[i].cost;
join(u,v);
}
}
return sum;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
gets(mp[0]);
memset(a,-1,sizeof(a));
memset(cost,0,sizeof(cost));
int tot=0;
for(int i=0;i<m;i++){
gets(mp[i]);
for(int j=0;j<n;j++){
if(mp[i][j]=='A' ||mp[i][j]=='S'){
a[i][j]=tot++;
}
}
}
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
if(a[i][j]!=-1){
bfs(i,j);
}
}
}
int sum=dij(tot);
printf("%d\n",sum);
}
return 0;
}
这个题输入的数据应该有坑。。。。坑了我几个小时,
gets(mp[0]);这样存缓冲就可以过
而getchar()就不能过。。。。。。。有毒啊