打ACM就像是表白,像我这样的人也就指着AC题目感受一下表白成功的感觉了。
题意:
方格迷宫内有一些外星人,要吧他们练成一棵最小生成树,求树长度。只有外星人和源点(和外星人的点没区别)可以当树的节点(这个我死活没看出来在哪里体现了,还好看到讨论区里的人说)
Input
On the first line of input there is one integer, N <= 50, giving the number of test cases in the input. Each test case starts with a line containg two integers x, y such that 1 <= x,y <= 50. After this, y lines follow, each which x characters. For each character, a space `` '' stands for an open space, a hash mark ``#'' stands for an obstructing wall, the capital letter ``A'' stand for an alien, and the capital letter ``S'' stands for the start of the search. The perimeter of the maze is always closed, i.e., there is no way to get out from the coordinate of the ``S''. At most 100 aliens are present in the maze, and everyone is reachable.
Output
For every test case, output one line containing the minimal cost of a succesful search of the maze leaving no aliens alive.
所以这个题肯定要先建图,先对每个点bfs求他们到其他点的距离,然后跑个prim就行了(prim复杂度为v^2,kruskal为eloge,这个图是密集图,跑prim更划算)
写的时候一开始被bfs坑爆了哦凑。。。
代码如下:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define mxn 60
#define inf 0x3f3f3f3f
#define mxp 1050
char map[mxn][mxn];
int dist[mxn][mxn];
int n,m;
int cnt;
int rec[mxn][mxn];
struct point{
int x,y;
point(int _x,int _y){x=_x,y=_y;}
point(){}
}p[mxp];
void bfs(int id){
point q[mxn*mxn];
int head=0,tail=1;
int d[mxn][mxn], mx[4]={0,1,0,-1},my[4]={1,0,-1,0};
bool flag[mxn][mxn];
memset(d,0x3f,sizeof(d));
memset(flag,0,sizeof(flag));
q[head]=p[id];
flag[p[id].x][p[id].y]=true;
d[p[id].x][p[id].y]=0;
while(head!=tail){
point now=q[head];
if(rec[now.x][now.y]!=-1)
dist[id][rec[now.x][now.y]]=d[now.x][now.y];
for(int i=0;i<4;++i){
int nx=now.x+mx[i],ny=now.y+my[i];
if(nx<0||ny<0||nx>=n||ny>=m||flag[nx][ny])
continue;
if(map[nx][ny]=='#') continue;
q[tail++]=point(nx,ny);
d[nx][ny]=d[now.x][now.y]+1;
flag[nx][ny]=true;
}
++head;
}
}
int prim(){
int dis[mxp];
memset(dis,0x3f,sizeof(dis));
int now=0,ret=0;
dis[now]=-1;
for(int i=1;i<cnt;++i){
int min_e=inf,min_p;
for(int j=0;j<cnt;++j){
if(dis[j]==-1) continue;
dis[j]=min(dis[j],dist[now][j]);
if(min_e>dis[j]){
min_e=dis[j];
min_p=j;
}
}
ret+=min_e;
now=min_p;
dis[min_p]=-1;
}
return ret;
}
int main(){
int cs;
scanf("%d",&cs);
while(cs--){
cnt=0;
memset(rec,-1,sizeof(rec));
memset(map,0,sizeof(map));
scanf("%d%d",&m,&n);
char eat[mxp];
gets(eat);
for(int i=0;i<n;++i)
gets(map[i]);
for(int i=0;i<n;++i)
for(int j=0;j<m;++j)
if(map[i][j]=='A'||map[i][j]=='S'){
rec[i][j]=cnt;
p[cnt].x=i,p[cnt++].y=j;
}
for(int i=0;i<cnt;++i)
bfs(i);
int ans=prim();
printf("%d\n",ans);
}
return 0;
}