http://poj.org/problem?id=1383
题目大意:
在图中找出距离最远的两点间的距离。
题目给出的图类似如下:( '#'代表障碍物, '.'代表可以通行的路 )
#######
#.#.###
#.#.###
#.#.#.#
#.....#
#######
本题思路:
这题暴力枚举每一点出发的最长路径显然不可行。
可以先在纸上模拟一下。从任意点A出发的最长路径的另一个端点称为B,我们或许可以发 ` 现
B就是全局最长路径的一个端点。接下来问题就很简单了,只要从B点开始搜索一遍图,就可以找到全局最长路径了。
这题的关键就是证明以上红色标注的文字成立。只要证明成立,那么这道题就可以用两次搜 索解决。以下是我自己给出的简短证明,如有证明不当之处请路人指出。
证明以上红色标注的文字成立:
假设:A为搜索起点,L[AB]为从A出发的最长路,B为该路径的另一端点。
待证明的问题是 : B一定是全局最长路的一个端点。
根据搜索起点A的不同分两种情况证明。
(一). A为全局最长路的一个端点。
该情况下显然L[AB]即为全局最长路,即B为全局最长路的另一个端点。
(二).A为非全局最长路端点的任意端点。
反证法:
1).设点B不是全局最长路的端点。
2).则一定存在一条全局最长路,设它的端点为C,D。
3).由2)得,l3 < min { l1, l2 }。(因为若l3>l1,则L[BD]就成为全局最长路了.)
4).由3)得 , min{ L[AC], L[AD] }>L[AB]。
5).这与假设相矛盾, 即L[AB]不是从A出发的最长路。
6).因此B一定是全局最长路的一个端点。
7).证毕。
程序代码:
#include <iostream>
using namespace std;
const int N = 1000;
const int Max = 5 * 100000;
const int Dir[4][2] = { {0, -1},
{0, 1},
{-1, 0},
{1, 0} };
//-------------------------- Object --------------------------//
/* graph */
char g[N][N];
int R, C;
/* state struct */
struct State
{
int p; // point
int len; // length
}Q[Max]; // queue
int front, rear; // queue pointer
/* max length and the farest point */
int maxLen, farPoint;
//------------------------- Function -------------------------//
/*
* Queue Operations
*/
void InitQueue()
{
front = rear = 0;
}
void Push( const int p, const int len )
{
Q[rear].p = p;
Q[rear].len = len;
++ rear;
}
State Pop()
{
State top = Q[ front++ ];
return top;
}
bool IsEmpty()
{
return front == rear;
}
/*
* end of Queue
*/
bool IsInMap( const int r, const int c )
{
return r >= 0 && r < R && c >= 0 && c < C;
}
/*
* BFS:get a lenghest path from startPoint
*/
void BFS( const int startPoint, const char white, const char gray )
{
// push initial state into queue
Push( startPoint, 1 );
g[ startPoint/C ][ startPoint%C ] = gray;
maxLen = 1, farPoint = startPoint;
// BFS
while( !IsEmpty() )
{
/* get queue top */
State top = Pop();
/* spread child state */
for( int i = 0; i < 4; ++ i ) {
int r = top.p/C + Dir[i][0];
int c = top.p%C + Dir[i][1];
if( !IsInMap(r, c) ) continue;
if( g[r][c] == white ) { /* spread to child state */
Push( r*C+c, top.len+1 );
g[r][c] = gray;
if( top.len + 1 > maxLen ) {
maxLen = top.len + 1;
farPoint = r*C+c;
}
}// if
}// for
}// while
}
int main()
{
freopen( "1.txt", "r", stdin );
int T;
scanf( "%d", & T );
while( T -- )
{
int sp;
scanf( "%d%d", & C, & R ); /* input graph */
for( int r = 0; r < R; ++ r )
{
getchar();
scanf( "%s", g[r] );
}
for( int i = 0; i < R * C; ++ i ) /* get start point */
if( g[i/C][i%C] == '.' ) {
sp = i;
break;
}
InitQueue(); /* first BFS */
BFS( sp, '.', '_' );
/*printf( "%d\n", farPoint );
for( int i = 0; i < C; ++ i )
{
printf( "%s\n", g[i] );
}*/
InitQueue(); /* second BFS */
BFS( farPoint, '_', '.' );
/*printf( "%d\n", farPoint );
for( int i = 0; i < C; ++ i )
{
printf( "%s\n", g[i] );
}*/
printf( "Maximum rope length is %d.\n", maxLen - 1 );
}
system( "pause" );
return 0;
}