求树的直径
树的直径是指树的最长简单路。求法: 两遍BFS :先任选一个起点BFS找到最长路的终点,再从终点进行BFS,则第二次BFS找到的最长路即为树的直径;
原理: 设起点为u,第一次BFS找到的终点v一定是树的直径的一个端点
证明: 1) 如果u 是直径上的点,则v显然是直径的终点(因为如果v不是的话,则必定存在另一个点w使得u到w的距离更长,则于BFS找到了v矛盾)
2) 如果u不是直径上的点,则u到v必然于树的直径相交(反证),那么交点到v 必然就是直径的后半段了所以v一定是直径的一个端点,所以从v进行BFS得到的一定是直径长度
(引用http://beyrens.blog.163.com/blog/static/9589445220109885810528/)
//9116963 NKHelloWorld 1383 Accepted 2552K 641MS G++ 1652B 2011-08-09 14:35:18 //7007#9116978 helloworld 1383 Accepted 2184K 641MS C++ 1697B 2011-08-09 14:36:09 //经修改后:时间变为: //9119386 NKHelloWorld 1383 Accepted 2188K 516MS C++ 1967B 2011-08-09 17:57:12 //修改内容有:将visit从bfs中移出,变为全局变量,节省80ms;少调用que.front(),节省40ms,将memset改为修改一圈边框,节约20ms #include <cstdio> #include <cstring> #include <queue> using namespace std; int T,C,R,ptr,ptc; bool visit[1010][1010]; char map[1010][1010]; int movement[4][2] = { -1,0,0,1,1,0,0,-1 }; struct NODE { int r,c,step; }; int bfs(int r,int c) { int ans = 0,i; memset(visit,false,sizeof(visit)); NODE now,temp; now.r = r; now.c = c; now.step = 1; visit[now.r][now.c] = true; queue<NODE> que; que.push(now); while(!que.empty()) { temp = que.front(); ans = temp.step; for(i=0;i<4;i++) { now.r = temp.r + movement[i][0]; now.c = temp.c + movement[i][1]; if(map[now.r][now.c]=='.' && visit[now.r][now.c]==false) { now.step = temp.step + 1; ptr = now.r; ptc = now.c; visit[now.r][now.c] = true; que.push(now); } } que.pop(); } return ans - 1; } int main() { int i,j,finalans; scanf("%d",&T); while(T-- > 0) { finalans = 0; scanf("%d%d",&C,&R); //memset(map,'#',sizeof(map)); for(i=0;i<=R+1;i++) map[i][0] = map[i][C+1] = '#'; for(j=0;j<=C+1;j++) map[0][j] = map[R+1][j] = '#'; for(i=1;i<=R;i++) scanf("%s",&map[i][1]); for(i=1;i<=R;i++) { for(j=1;j<=C;j++) { if(map[i][j]=='.') { bfs(i,j); printf("Maximum rope length is %d.\n",bfs(ptr,ptc)); break; } } if(j<=C) break; } } return 0; }