題目描述:
乙個n*m的地圖, 求出相距最遠的兩個空地間之間的距離。保證地圖中任意兩個空地之間有且僅有一條路徑。n,m<1000
分析:
可以看出,整個地圖的路徑可以構成一棵樹。題目就是要求這棵樹中距離最遠的兩個點。
假設我們已經把這棵樹建好了,我用了乙個很短的遞迴函式maxlen求出了這個樹的最長路,這個遞迴函式返回以頂點p為根的樹的深度:
1.若p是葉子,則返回0。
2.若p不是葉子,則計算它的每個子樹的深度m=maxlen(son[i])+len[p,son[i]](注意,子樹的個數不會超過3)
3.若子樹的深度最大和次大之和大於ans,則更新ans的值。ans是外部變數記錄當前的最長路。
4.返回最大的子樹深度。
這個函式不到20行。要注意的是由於是矩陣地圖,所以任意乙個點相鄰的空地最多4個,看作有向樹的話,子樹最多3個。在儲存的時候可以節省一些空間和時間。
現在要做的就是把地圖轉換為樹。
轉換的時候使用廣度優先搜尋,也沒太多技巧。只有遇到死胡同和岔路的點,才把它加入到樹的節點中。
貼一下**,2秒多ac的:
/*zju2013 labyrinth
*/#include
#include
#define n 1002
#define clr(a) memset(a,0,sizeof(a))
struct nodepoint;
typedef struct nodepoint node;
struct nodesearch;
typedef struct nodesearch point;
int dir[2]=,,,};
int c,r;
int ans;
char a[n][n];
char e[n][n];
node b[n*n/2][4];
point d[n*n/2];
int out(int x,int y)
int neighbour(int x0,int y0,char ch)
return c;
}//creat a tree
int creattree(char a[n],node b[4])
//each dir
for(k=0;k<4;k++)
}p++;
}//end bfs
return m;
}//return the max depth under node p
int maxlen(int p)
else if(m>=m2)
}len=m1+m2;
if(len>ans) ans=len;
return m1;
}int main()
//system("pause");
return 0;
}sample input
33 3
####.#
###7 6
#######
#.#.###
#.#.###
#.#.#.#
#.....#
#######
7 6#######
#.....#
#.#.###
#.#.#.#
#.#...#
#######
sample output
maximum rope length is 0.
maximum rope length is 8.
maximum rope length is 11.
SDOI2013 直徑(樹的直徑)
小q最近學習了一些圖論知識。根據課本,有如下定義。樹 無迴路且連通的無向圖,每條邊都有正整數的權值來表示其長度。如果一棵樹有n個節點,可以證明其有且僅有n 1 條邊。路徑 一棵樹上,任意兩個節點之間最多有一條簡單路徑。我們用 dis a,b 表示點a和點b的路徑上各邊長度之和。稱dis a,b 為a...
求樹的直徑 樹中最長路
對於一顆有邊權的樹,它的直徑表示樹中最遠的兩個節點之間的距離,可以通過兩次深搜 廣搜 來求出直徑 從任意起點s開始,求出到s的最遠的節點node,然後再從node開始求出到node最遠的節點,搜尋的過程中更新節點的值和距離,貌似還可以用樹形dp來求,剛剛做的一道題,當時感覺是兩倍的權值和減去乙個最遠...
基環樹的最長鏈
本題給定幾個基環樹的森林,求每棵基環樹的直徑長度之和 思路 先單獨考慮一棵基環樹,先dfs找環 也可tarjan 先把每個環上的點向外擴充套件,找出它們每棵子樹的直徑,用樹型dp處理,接著拆環成鏈,再複製一倍的鏈長,在環上跑,用單調佇列維護即可,但是維護前還需要預處理下直徑字首和,否則會爆時間。來自...