這題還是比較難的。
首先建圖方面,如果單純的把單詞作為點,能拼接的關係作為邊,那麼就是哈密頓圖(每個點僅能走一次),難度比較大。
換一種思路,就是把每個單詞看成一條有向邊,由該單詞的首字母指向尾字母。
那麼這題便是尤拉圖的問題了。
本質上採用的還是搜尋,但是為了快速得到字典序最小的尤拉路徑,首先要對單詞集進行排序。
排完序後,用邊集陣列存圖;再通過計算各點的出度與入度,同時判斷基圖(不考慮邊的方向的圖)的連通性,判斷是否存在尤拉迴路或尤拉通路。
如果存在尤拉迴路,那麼就從0開始搜尋;
如果存在尤拉通路,那麼就從「出度=入度+1」的點開始搜尋。
參考**如下:
邊集陣列存圖+並查集判斷連通性
#include
using namespace std;
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct enode;
enode edge[1010];
string s[1010];
int n,m,fa[1010];
int flag[1010];
int path[1010];
int visit[1010];
int root(int x)
void uset(int x,int y)
//並查集判斷連通性
int judge()
void find(int u)
sort(s,s+n);
for (i=0;i<26;++i) fa[i]=i;
int in[30],out[30];
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for (i=0;i0;--i)
cout << edge[path[i]].s << ".";
cout << edge[path[0]].s << endl;
}else cout << "***" << endl;
}return 0;
}
並查集(判斷環路)
並查集是非常常用的一種資料結構,用於把資料按照規則整理成集合,集合最終呈現為樹狀結構,以根節點作為不同集合的區分標誌,實現方面主要涉及查詢和合併,如下 查詢 int find int x return r 合併 void unionset int x,int y 不難理解,其目的就是為了構建乙個森林...
求連通塊(並查集實現)
連通塊可以理解為無向圖中有幾個連通的點集,那麼這個過程與並查集的原理就極其相似了,將點集看作並查集的祖先和他的後代們,相互連通的點就放在同一祖先下,這樣只需要查詢共有幾個祖先即可。下面來一道例題深入理解下 jsoi2008 星球大戰 當我們加入乙個點時,先假設又加入乙個單獨的連通塊,然後再掃一下與它...
並查集,動態連通性
n,m n個點,m條邊 隨之而來m條邊 q 代表q個操作 q行,每行乙個序號,代表將第m個輸入的邊刪除,問刪除後有多少個連通塊。思路 我們將m條邊,和q詢問記錄下來,並將要刪除的邊標記。然後對那些不用的邊使用並查集,並算出有多少個連通塊。然後從最後乙個詢問開始,依次將那些邊加入並查集,如果加入時,兩...