POJ 2513 字典樹 一筆畫問題

2021-07-22 18:02:49 字數 2407 閱讀 6380

大致題意:

給定一些木棒,木棒兩端都塗上顏色,求是否能將木棒首尾相接,連成一條直線,要求不同木棒相接的一邊必須是相同顏色的。

解題思路:

可以用圖論中尤拉路的知識來解這道題,首先可以把木棒兩端看成節點,把木棒看成邊,這樣相同的顏色就是同乙個節點

問題便轉化為:

給定乙個圖,是否存在「一筆畫」經過塗中每一點,以及經過每一邊一次。

這樣就是求圖中是否存在尤拉路euler-path。

回顧經典的「七橋問題」,相信很多同學馬上就明白了什麼是 尤拉路 了,這裡不多作解釋。

由圖論知識可以知道,無向圖存在尤拉路的充要條件為:

① 圖是連通的;

② 所有節點的度為偶數,或者有且只有兩個度為奇數的節點。

其中①圖的連通性用程式判斷比較麻煩,先放一下。

這裡先說說②關於度數的判斷方法:

blue

magenta

violet

cyan

red

節點的度用顏色出現次數來統計,如樣例中,藍色blue出現三次(不管是出度還是入度),那麼blue結點的度就為3,同樣地,我們也可以通過輸入得到其他全部結點的度,於是,我們有:

blue=3

red=2

violet=1

cyan=2

magenta=2

用乙個一維陣列就能記錄了,然後分別 模2,就能判斷顏色結點的奇偶性

只要奇度數的結點數的個數 = 1 或 >=3 ,即使①圖連通,尤拉路也必不存在

但是若 奇度數的結點數的個數 為0或 ==2,那麼我們繼續進行①圖的連通性證明:

證明①圖的連通性,使用並查集mergeset是非常高效的方法。

基本方法:

初始化所輸入的n個結點為n棵樹,那麼就有乙個n棵樹的森林,此時每棵樹的有唯一的結點(根),該結點的祖先就是它本身。再通過不斷地輸入邊,得到某兩個結點(集合)之間的關係,進而合併這兩個結點(集合),那麼這兩個集合就構成乙個新的集合,集合內的所有結點都有乙個共同的新祖先,就是這個集合(樹)的根。

最後只要列舉任意乙個結點,他們都具有相同的祖先,那麼就能證明圖時連通的了。

但是單純使用並查集是會超時的,因為這樣會導致每次尋找某個結點的祖先時,平均都會花費o(n/2)時間,最壞情況,當n==50w時,o(n/2)大概為25ms,那麼要確定50w個結點是否有共同祖先時,總費時為50w*25ms ,鐵定超,不算了= =

因此必須使用並查集時必須壓縮路徑,前幾次搜尋某個結點k的祖先時,在不斷通過父親結點尋找祖先結點時,順便把從k到最終祖先結點s中經過的所有結點的祖先都指向s,那麼以後的搜尋就能把時間降低到o(1)

由於並查集必須利用 陣列的下標 與 儲存的物件,使用int是比較方便的處理方法,但是題目的「顏色結點」是string,不方便用來使用並查集,即使用map也不行,雖然stl的map是基於hash的基礎上,但並不高效,在本題中使用會超時。

這個題目涉及了多個基本資料結構和演算法,綜合性很強,非常有代表性,能夠a到這題確實是受益良多。

#include 

#include

#define maxs 500010

#include

#include

#define mme(i,j) memset(i,j,sizeof(i))

using

namespace

std;

int father[maxs],deg[maxs];

char head[15],tail[15];

int find_father(int x)

/*void joint(int x,int y)

*/typedef

struct node

trienode,*trie;//trie 樹

trie creat()

trie root;

void insert(char *s,trie root,int num)

p=p->nexts[id];

i++;

}p->num=num;

}int find(char *s,trie root)

p=p->nexts[id];

i++;

}return p->num;

}void init()

}void clear_trie(trie root)

bool ok(int cnt)

if(odd<=2)

return

1; return0;}

int main()

if(ok(cnt))

puts("possible");

else

puts("impossible");

clear_trie(root);

return

0;}

poj 2513(字典樹 尤拉通路)

題意 給你n個火柴棍,每個火柴棍頭和尾兩種顏色,問你是否存在能夠把這些火柴棍擺成一行的情況,兩個相連的火柴棍的顏色需要一樣 解題思路 最初的思路是用map標記顏色,然後把每種顏色看作點,每根火柴棍看作邊,求尤拉路徑,然後超時了。看了別人的寫法,想起來了自己還學過字典樹來著。然後用字典樹找就行了,快很...

一筆畫問題

一筆畫問題是在6x6的棋盤上分布著若干點,從紅色起點開始依次不重複地經過每個白色點,已經經過的點可以跨越過去。程式採用深度搜尋,從紅色點開始分別往上 往下 往左和往右邁出第一步,然後沿著當前方向,分別探測左邊 前面和右邊的下一結點,標記已經經過的節點為空。探測到左邊有節點就左轉,然後直行到該節點 如...

一筆畫問題

描述 判斷乙個圖是否能夠用一筆畫下來.規定,所有的邊都只能畫一次,不能重複畫。輸入第一行只有乙個正整數n n 10 表示測試資料的組數。每組測試資料的第一行有兩個正整數p,q p 1000,q 2000 分別表示這個畫中有多少個頂點和多少條連線。點的編號從1到p 隨後的q行,每行有兩個正整數a,b ...