poj 1383 广搜 类似于树的直径

来源:互联网 发布:webassembly与java 编辑:程序博客网 时间:2024/06/05 00:08

因为题目告诉我们每两点间只有一条路相连  that there is exactly one path between any two free blocks. 

就可以把点之间形成的路径看成是一棵树

题目又要我们找最长的一条路,瞬间就可以转换成树的最长路来做了

结论是从树上的任何一点出发,能搜到的最远的点肯定是最长链上的一端,再从这一端出发,能搜到的最远的点的距离即为答案

证明过程详见

View Code
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct point{
int x,y;
int d;
}s,da[1010];
int dir[4][2]={0,1,1,0,0,-1,-1,0};
int flag[1010][1010];
int n,m,Max,ax,ay;
char g[1010][1010];
void bfs(){
memset(flag,0,sizeof(flag));
flag[s.x][s.y]=1;
queue<point> Q;
Q.push(s);Max=0;
while(!Q.empty()){
point fr=Q.front();Q.pop();
for(int i=0;i<4;i++){
point tmp;
tmp.x=fr.x+dir[i][0];
tmp.y=fr.y+dir[i][1];
if(tmp.x<1||tmp.x>n||tmp.y<1||tmp.y>m||flag[tmp.x][tmp.y]||g[tmp.x][tmp.y]=='#') continue;
flag[tmp.x][tmp.y]=1;
tmp.d=fr.d+1;
if(tmp.d>Max) {
Max=tmp.d;
ax=tmp.x;ay=tmp.y;
}
Q.push(tmp);
}
}
}
int tot;
int main(){
int t,i,j,a,b;
scanf("%d",&t);
while(t--){
scanf("%d%d",&m,&n);
for(i=1;i<=n;i++) scanf("%s",g[i]+1);
for(i=1;i<=n;i++){
int f=0;
for(j=1;j<=m;j++)
if(g[i][j]=='.'){f=1; a=i;b=j;break;}
if(f) break;
}
s.x=a;s.y=b;s.d=0;
bfs();int ans=0;
s.x=ax;s.y=ay;s.d=0;
bfs();
printf("Maximum rope length is %d.\n",Max);
}
}