背景:地球又被外星人攻击了,现在我们要抓住这些外星人。为了更快地抓住他们,地球人学会了分身术。
题意:给出一个迷宫,A表示外星人的位置,S表示你的位置。你可以在分出很多分身去抓外星人,求所有的你抓住外星人走的最短步数。
解0.5:最小生成树似乎实际例子很喜欢出分裂,比如上次衍生出新的卡车,比如这次分身。(突然发现今天怎么又能打出中文句号了)
解0.7:看出是最小生成树后你和外星人就没有区别了(?)都是结点,现在要根据迷宫建边。一开始想有什么好办法能直接求最小生成树,但迷宫是不确定的,好在点最多只有2500个,建一个完全图也就是2500^2,可以接受。因此对每个点重新编号,暴力dfs连边后跑krus即可。
解0.8:编号的时候注意不要在原图上改,如果直接改成数字会和'#'冲突从而WA掉,还是再开一个矩阵存编号吧!另外,这题先输入m再输入n。
解0.9:交一发是不是TLE了?如果用c++的String类和cin确实会T。
解0.95:什么?还在WA?如果你读完m和n后读取空格的gets对应存储空间大小只有10,那么吸收不干净poj的诡异空格的。开它100个char。
解1.0:终于AC了当绝望地试了各种玄学方法包括把下标从1开始改成从0开始的异世界生活后与别人的代码逐行比对发现好像真的只有这个数组大小有影响改完A了室友问我晚饭是不是被下了毒啊那确实。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include <algorithm> 3 #include <queue> 4 #include <math.h> 5 using namespace std; 6 #define ll long long 7 #define maxx 505 8 #define inf 0x3f 9 const int mod=1e9+7; 10 //#define int long long 11 char s[maxx][maxx]; 12 int xx[4]={0,1,0,-1}; 13 int yy[4]={1,0,-1,0}; 14 int vis[maxx][maxx]; 15 int mark[maxx][maxx]; 16 struct edge{ 17 int u,v,w; 18 bool operator< (const edge &a)const{ 19 return w<a.w; 20 } 21 }a[maxx*maxx]; 22 int cnt; 23 struct node{ 24 int x,y,dis; 25 }nxt,st; 26 void add(int u,int v,int w){ 27 a[++cnt].u=u; 28 a[cnt].v=v; 29 a[cnt].w=w; 30 } 31 int n,m,num; 32 int fa[maxx*maxx]; 33 int find(int x){ 34 return fa[x]==x?x:fa[x]=find(fa[x]); 35 } 36 int krus(){ 37 for(int i=0;i<maxx*maxx;i++) 38 fa[i]=i; 39 sort(a+1,a+cnt+1); 40 int ans=0,cnt2=0; 41 for(int i=1;i<=cnt;i++){ 42 int u=find(a[i].u),v=find(a[i].v); 43 if(u!=v){ 44 fa[u]=v; 45 ans+=a[i].w; 46 cnt2++; 47 if(cnt2==num-1) 48 return ans; 49 } 50 } 51 return ans; 52 } 53 void bfs(int x,int y){ 54 memset(vis,0,sizeof vis); 55 queue<node> q; 56 nxt.x=x,nxt.y=y,nxt.dis=0; 57 q.push(nxt); 58 vis[x][y]=1; 59 while(!q.empty()){ 60 node now=q.front(); 61 q.pop(); 62 if(s[now.x][now.y]=='A'||s[now.x][now.y]=='S') 63 add(mark[x][y],mark[now.x][now.y],now.dis); 64 for(int i=0;i<4;i++){ 65 int tx=now.x+xx[i],ty=now.y+yy[i]; 66 if((!vis[tx][ty])&&tx>=0&&tx<n&&ty>=0&&ty<m&&s[tx][ty]!='#') { 67 vis[tx][ty] = 1; 68 nxt.x = tx, nxt.y = ty, nxt.dis = now.dis + 1; 69 q.push(nxt); 70 } 71 } 72 } 73 } 74 signed main() { 75 int T; 76 scanf("%d",&T); 77 while(T--){ 78 cnt=0,num=0; 79 char c[15]; 80 scanf("%d%d",&m,&n); 81 gets(c); 82 for(int i=0;i<n;i++) { 83 gets(s[i]); 84 for (int j = 0; j < m; j++) 85 if(s[i][j]=='A'||s[i][j]=='S') 86 mark[i][j]=++num; 87 } 88 for(int i=0;i<n;i++) { 89 for (int j = 0; j < m; j++) 90 if (s[i][j] == 'A' || s[i][j] == 'S') 91 bfs(i, j); 92 } 93 printf("%d\n",krus()); 94 } 95 return 0; 96 }