Graph хэдэн connected component-оос (холбоотой хэсгээс) тогтохыг DFS-ээр тоолох арга.
Эхлээд жижиг бодлого
6 node-той graph-т 1-2, 2-3, 4-5 гэсэн гурван edge байна. Хэдэн тусдаа хэсэг байна вэ?
Node 1-ээс 2, 3 хүрнэ: энэ нь эхний component. Node 4-өөс 5 хүрнэ: хоёр дахь component. Node 6 ганцаараа: гурав дахь component. Хариу 3, comp array нь 1 1 1 2 2 3.
Энгийн аргаас санаа руу
Энгийн арга бол node хос бүрийн хувьд "хоорондоо path байна уу?" гэж тусад нь хайх. n = 1000 бол хагас сая хос, хос бүрт бүтэн хайлт хийнэ. Хэт удаан.
Гол санаа: нэг node-оос DFS эхлүүлбэл тэр node-ын component-ын бүх node-д нэг дор хүрнэ. Тиймээс node-уудыг дарааллаар нь харж, хараахан тэмдэглэгдээгүй node олдох бүрт шинэ component эхлүүлээд DFS явуулна. Ингэхэд node бүрт яг нэг удаа орно.
Нэр томьёо ба тэмдэглэгээ
- connected component
- Хоорондоо path-аар холбоотой node-уудын хамгийн том бүлэг. Монголоор "холбоотой хэсэг".
- comp[u]
- Node u аль component-од орсныг заана. 0 бол хараахан ороогүй.
- cnt
- Одоогоор олдсон component-ын тоо. Шинэ component эхлэх бүрт 1-ээр нэмэгдэнэ.
- dfs(u)
- Node u-д орж, тэмдэглэгдээгүй хөрш бүр рүү гүнзгийрч орох recursive function.
Graph хэдэн connected component-оос тогтох вэ? Node-уудыг 1, 2, … n гэж дарааллаар нь шалгана. Аль ч component-од ороогүй node олдвол тэндээс DFS эхлүүлж, хүрч болох бүх node-ыг нэг component гэж тэмдэглэнэ.
- Space тоглуулах
- ←→ алхам
- −+ хурд
- Одоогийн node / edge
- Шинэ component-ын эхлэл
- Одоогийн component-од орсон
- Өмнөх component-ууд / DFS-ийн явсан edge
Хэдэн арал байна?
Далайд хэдэн арал байгааг тоолъё. Нэг арлын хотууд хоорондоо замаар холбоотой, харин өөр арал руу зам байхгүй. Graph дээр ийм арлыг connected component гэнэ.
Дараа нь юу болох вэ?
Оноо 0 / 00дараалсан зөв, хамгийн их 0
Animation нэг алхам дээр зогсоно. Дараа нь код юу хийх вэ? Таагаад оноо цуглуул! Нэвтрэх хэрэггүй, оноо чинь энэ төхөөрөмж дээр хадгалагдана.
Юунд хэрэгтэй вэ?
Ямар хотууд хоорондоо замаар холбоотой, аль нь тусдаа вэ гэдгийг олно. Олимпиадын graph бодлогын эхний алхам ихэвчлэн component-уудыг олох байдаг.
Яаж ажилладаг вэ?
1. comp[i] = 0 бол node i аль ч component-од ороогүй гэсэн үг. 2. Node-уудыг 1, 2, … n гэж дарааллаар нь шалгана. 3. Component-од ороогүй node олдвол cnt-г 1-ээр нэмээд тэндээс DFS эхлүүлнэ. 4. DFS-ийн хүрсэн бүх node-д comp = cnt гэж бичнэ. 5. Эцэст нь cnt бол component-ын тоо, comp бол node бүрийн component-ын дугаар. Оролт: n m, дараа нь m мөрөнд «u v» (чиглэлгүй edge, node 1…n).
Яагаад зөв, хэр хурдан бэ?
DFS эхэлсэн node-оос path-аар хүрч болох бүх node-д заавал очно, өөр component-ын node-д хэзээ ч очихгүй. Тиймээс нэг DFS яг нэг component-ыг бүтнээр нь тэмдэглэнэ. Main дотор тэмдэглэгдээгүй node олдох бүрт cnt нэмэгддэг тул cnt нь component-ын тоотой тэнцүү.
Node бүрт нэг удаа орж, edge бүрийг хоёр талаас нь нэг нэг удаа харна. Хугацаа O(n + m). n = 100 000, m = 200 000 бол хэдэн зуун мянган үйлдэл л болно.
Түгээмэл алдаа
- Чиглэлгүй edge-ийг нэг л тал руу нь нэмэх.
g[u].push_back(v)хийгээдg[v].push_back(u)-г мартвал DFS зарим node-д хүрэхгүй. - Маш урт гинж (n = 100 000) дээр recursive DFS stack overflow өгч болно. Тэгвэл queue-тэй BFS эсвэл өөрийн stack ашигла.
- Edge-гүй node-ыг мартах. Ийм node ганцаараа нэг component тул cnt-д заавал орно.
Хязгаарын тохиолдол
- m = 0: node бүр тусдаа component, хариу n.
- Бүх node холбоотой: нэг л DFS бүгдийг тэмдэглэнэ, хариу 1.
- Давхар edge (
1-2хоёр удаа): хоёр дахь удаад хөрш нь аль хэдийн тэмдэглэгдсэн тул алгасна, хариу өөрчлөгдөхгүй.
Өөрийгөө шалга
5 node-той, edge огт байхгүй graph хэдэн component-той вэ?
Хариу харах
5. Node бүр ганцаараа нэг component.
Яагаад comp[i] != 0 үед node i-д шинэ DFS эхлүүлэхгүй вэ?
Хариу харах
Тэр node өмнөх DFS-ээр тэмдэглэгдсэн, өөрөөр хэлбэл түүний component аль хэдийн тоологдсон.
Гурван дадлага
Hint-ээ нээхээс өмнө өөрөө оролдоорой.
1.7 node, edge нь
1-4,2-5,4-7,3-6. Код юу хэвлэхийг гараар ол.Hint харах
Node 1, 2, 3 гэж дарааллаар нь шалга. Тэмдэглэгдээгүй node бүрээс шинэ дугаар эхэлнэ.
Хариу ба тайлбар
Эхний мөрөнд 3, хоёр дахь мөрөнд
1 2 3 1 2 3 1. Component-ууд нь {1, 4, 7}, {2, 5}, {3, 6}.2.Хамгийн том component хэдэн node-той болохыг хэвлэдэг болго.
Hint харах
Main доторх loop дууссаны дараа comp array-аар нэг явж, дугаар бүр хэдэн удаа гарсныг тоол.
Хариу ба тайлбар
vector<int> sz(cnt + 1);үүсгээдfor (int i = 1; i <= n; i++) sz[comp[i]]++;гэнэ. Хариу нь sz-ийн хамгийн их утга.3.Graph-ыг бүхэлд нь холбоотой болгохын тулд хамгийн цөөндөө хэдэн edge нэмэх вэ?
Hint харах
Нэг шинэ edge хоёр component-ыг нэг болгож чадна.
Хариу ба тайлбар
cnt - 1. Component бүрээс нэг node сонгоод тэднийг гинж шиг холбоход хүрнэ. Үүнээс цөөн edge-ээр бүх component-ыг нэгтгэх боломжгүй.
Жишээ
Оролт
8 6 1 2 1 3 4 5 6 7 7 8 6 8
Гаралт
3 1 1 1 2 2 3 3 3
Одоо өөрөө бодоод үз
Хичээл
Энэ сэдвийн хичээл удахгүй нэмэгдэнэ.