11438๋ฒ: LCA 2
์ฒซ์งธ ์ค์ ๋ ธ๋์ ๊ฐ์ N์ด ์ฃผ์ด์ง๊ณ , ๋ค์ N-1๊ฐ ์ค์๋ ํธ๋ฆฌ ์์์ ์ฐ๊ฒฐ๋ ๋ ์ ์ ์ด ์ฃผ์ด์ง๋ค. ๊ทธ ๋ค์ ์ค์๋ ๊ฐ์ฅ ๊ฐ๊น์ด ๊ณตํต ์กฐ์์ ์๊ณ ์ถ์ ์์ ๊ฐ์ M์ด ์ฃผ์ด์ง๊ณ , ๋ค์ M๊ฐ ์ค์๋ ์
www.acmicpc.net
ํฌ์ ํ ์ด๋ธ์ ๋ํด ๋ชจ๋ฅธ๋ค๋ฉด ํ๊ธฐ ์ด๋ ค์ด ๋ฌธ์ ์ผ๊ฑฐ ๊ฐ์ต๋๋ค.
ํ๊ธฐ์ ์ ํฌ์ ํ ์ด๋ธ๋ก ์๋ฐ์ ์ ํ๊ณ ์ฒ์ฒํ ํ์ด๋ณด์. ์๋ ์ฃผ์๋ ํฌ์ ํ ์ด๋ธ์ ๊ดํ ๋ฌธ์ ์ ๋๋ค.
[Algorithm/ Sparse Table (ํฌ์ํ ์ด๋ธ)] ๋ฐฑ์ค 17435๋ฒ๊ณผ ํจ๊ป (tistory.com)
[Algorithm/ Sparse Table (ํฌ์ํ ์ด๋ธ)] ๋ฐฑ์ค 17435๋ฒ๊ณผ ํจ๊ป
Sparse Table (์คํ์ค ํ ์ด๋ธ) ํน์ง ๋ฐฉํฅ ๊ทธ๋ํ ์ ๋๋ค. ๋ชจ๋ ์ ์ด ๋ชฉ์ ์ง๊ฐ ์์ต๋๋ค. ๊ทธ ์ ์ ํ๊ณ ์๋ก์ด ์ ์ผ๋ก ๊ฐ๋๋ค. 2์ ์ ๊ณฑ๊ทผ์ผ๋ก ๋์ฐฉํ ์ ์ ์ ์ฅํฉ๋๋ค. (1๋ฒ, 2๋ฒ, 4๋ฒ, 8๋ฒ ์ด๋์ ๋ํ
cclient.tistory.com
๋ค์ LCA 2๋ก ๋์์์ ๋ฌธ์ ๋ฅผ ๋ณด์. LCA์ ๋ค๋ฅธ ์ ์ ์ฃผ์ด์ง๋ ์ ์ ์ ์์ ๋ ธ๋์ ์ ์ ๋๋ค. ์ฆ ์ด์ ์ ํ์๋๊ฑฐ๋ณด๋ค ๋ ํจ.์จ.์ .์ผ.๋ก ํ์ด์ผ ํฉ๋๋ค.
LCA2๋ฅผ ๊น์ด๋ฅผ ๋ง์ถ ํ ์กฐ์์ด ๊ฐ์ ๋๊น์ง ์ฌ๋ผ๊ฐ๊ฒ ๋๋ฉด ์๊ฐ ๋ณต์ก๋๋
์ฟผ๋ฆฌ ํ์ M * 1ํ ์ฐ์ฐ์ ์๊ฐ N = O (MN)
์ต๋ M(100,000) * N(100,000) = 10,000,000,000 ์ด ๋ฉ๋๋ค.. ์๊ฐ์ด๊ณผ !! ์๊ฐ์ด๊ณผ!!
![](https://t1.daumcdn.net/keditor/emoticon/friends1/large/037.gif)
๋ฌธ์ ์์ ์ฃผ์ด์ง ์์ ๋ฅผ ๊ฐ์ง๊ณ ํจ.์จ.์ .์ผ.๋ก ์ฒ์ฒํ ํ์ด๋ด ์๋ค.
์ฒซ๋ฒ์งธ, ์ฃผ์ด์ง๋ ๋ ธ๋์ ์์ ๊น์ด๋ฅผ ๋น๊ตํด์ผ ํฉ๋๋ค! ์๋ํ๋ฉด ๊น์ด๋ฅผ ๋ง์ถฐ์ฃผ๊ณ Root ๋ฐฉํฅ์ผ๋ก ํจ๊ป ์ฌ๋ผ๊ฐ๋ฉด์ ๊ฐ์ฅ ๊ฐ๊น์ด ์กฐ์์ ์ฐพ์์ผ ํจ์จ์ด ์ข๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ๋ฌ๋ฉด ๊ฐ๊ฐ์ ๋ ธ๋์ ๊น์ด๋ฅผ ์์์ผ ๊ฒ ์ฃ ? ์ผ๋จ ๊น์ด๋ฅผ ์ ์ฅํด ์ค๋๋ค. DFS๋ก!
- vector<int> gLink[100'101]; - ์ฐ๊ฒฐ๋์ด ์๋ ๋ ธ๋๋ฅผ ๋ฒกํฐ์ ์์ ๋ฃ์ด์คฌ์ต๋๋ค.
- int gDepth[100'001]; - ๋ฐฉ๋ฌธ์ฒ๋ฆฌ ๋ฐฐ์ด์ ํ๋ ๋ ๋ง๋ค๊ณ ์ถ์ง ์์์ ๋ฐฉ๋ฌธ ํ์ง ์์ ๋๋ ๋ชจ๋ -1๋ก ์ด๊ธฐํ ํด์คฌ์ต๋๋ค. memset(gDepth, -1, sizeof(gDepth)); (ํค๋: memory.h)
void DFS(int pIdx, int pDepth)
{
if(gDepth[pIdx] == -1)
gDepth[pIdx] = pDepth;
for (size_t i = 0; i < gLink[pIdx].size(); ++i)
{
int aNext = gLink[pIdx][i];
if (gDepth[aNext] == -1)
DFS(aNext, pDepth + 1);
else
continue;
}
}
์ฝ๋๋ฅผ ์คํํ ๊ฒฐ๊ณผ ์ ๋๋ค. ์ ๊ฐ ์์ ๊ทธ๋ ค๋์ ๊น์ด์ ๋์ผํ๊ฒ ์ ๋ค์ด ๊ฐ ๊ฑธ ํ์ธ ํ ์ ์์ต๋๋ค.
๋๋ฒ์งธ, 2์ ์ ๊ณฑ๊ทผ์ผ๋ก ๊ฐ๊ฐ ๋ ธ๋์ ๋ถ๋ชจ๋ฅผ ์ ์ฅํด์ค๋๋ค. ๋น๊ตํ ์ต์ด์ ํ ์ด๋ธ์ด ์์ด์ผํ๊ธฐ ๋๋ฌธ์ ์ด๊ธฐ ์ธํ ์ ํด์ฃผ๊ณ ๋๋จธ์ง๋ฅผ ์ซ~~์ ํด์ค๋๋ค. ์ด๊ธฐ ์ธํ ์ ํ์ฌ ๋ ธ๋์ ๋ถ๋ชจ๋ฅผ ์ ์ฅํ๊ณ ์์ํ ๋ ์๋ ํ ์ฒ๋ผ ์ ์ฅ์ด ๋ ๊ฒ๋๋ค.
์ด๊ธฐ ์ธํ ๋ค์ ์ฝ๋๋
15์ ๋ถ๋ชจ๊ฐ ์ ์ฅ๋์ด ์๋ gSparseTable [0][15]์์ ๊ฐ(x:11)์ ๋ฐ์์ ๋ค์ gSparseTable [0][๊ฐ(x:11)]์์ ๊ฐ(y: 5)์ ๋ฐ์ผ๋ฉด ์ด ๊ฐy๋ 15์ ํ ๋จธ๋& ํ ์๋ฒ์ง๊ฐ ๋ฉ๋๋ค.
void LCA(int pN)
{
// ์ด๊ธฐ ์ธํ
------------------------------------
for (int i = 1; i <= pN; ++i)
{
for (size_t j = 0; j < gLink[i].size(); ++j)
{
if (gDepth[i] < gDepth[gLink[i][j]])
{
gSparseTable[0][gLink[i][j]] = i;
}
else
{
gSparseTable[0][i] = gLink[i][j];
}
}
}
// -----------------------------------------------
for (int i = 1; i < st; ++i)
{
for (int j = 1; j <= pN; ++j)
{
int temp = gSparseTable[i - 1][j];
gSparseTable[i][j] = gSparseTable[i - 1][temp];
}
}
}
์ธ๋ฒ์งธ, ๊น์ด๋ฅผ ์ผ์น ์์ผ ์ค๋๋ค.
int aFindDepth (int pParm, int pDiff)
{
int cur = pParm;
for (int i = 0; i < st; ++i)
{
if (pDiff & (1 << i))
{
cur = gSparseTable[i][cur];
}
}
return cur;
};
์... ๋ง์ง๋ง ๊น์ด๋ฅผ ๋ง์ท๋๋ฐ ์์ง ์ต์ ๊ณตํต ์กฐ์์ ๋ง๋๊ธฐ ์ ์ด๋ฉด ๊ฐ์ด ์ฌ์ด ์ข๊ฒ ์ฌ๋ผ๊ฐ ์ค๋๋ค.
int FindLCA(int pA, int pB, int pN)
{
int H = 0;
while (pN > 1)
{
pN /= 2;
H++;
}
if (pA != pB)
{
for (int i = H; i >= 0; --i)
{
if(gSparseTable[i][pA]!=0 && gSparseTable[i][pA]!= gSparseTable[i][pB])
{
pA = gSparseTable[i][pA];
pB = gSparseTable[i][pB];
}
}
return gSparseTable[0][pA];
}
else
{
return pA;
}
}
์ด ํฉ ์ฝ ๋ ... ์๊ณ ํ์ จ์ต๋๋ค ~
/hide
#include <iostream>
#include <vector>
#include <memory.h>
using namespace std;
constexpr int st = 21;
vector<int> gLink[100'101];
int gSparseTable[st][100'001];
int gDepth[100'001];
void DFS(int pIdx, int pDepth)
{
if(gDepth[pIdx] == -1)
gDepth[pIdx] = pDepth;
for (size_t i = 0; i < gLink[pIdx].size(); ++i)
{
int aNext = gLink[pIdx][i];
if (gDepth[aNext] == -1)
DFS(aNext, pDepth + 1);
else
continue;
}
}
void LCA(int pN)
{
// ์ด๊ธฐ ์ธํ
------------------------------------
for (int i = 1; i <= pN; ++i)
{
for (size_t j = 0; j < gLink[i].size(); ++j)
{
if (gDepth[i] < gDepth[gLink[i][j]])
{
gSparseTable[0][gLink[i][j]] = i;
}
else
{
gSparseTable[0][i] = gLink[i][j];
}
}
}
// -----------------------------------------------
for (int i = 1; i < st; ++i)
{
for (int j = 1; j <= pN; ++j)
{
int temp = gSparseTable[i - 1][j];
gSparseTable[i][j] = gSparseTable[i - 1][temp];
}
}
}
int aFindDepth (int pParm, int pDiff)
{
int cur = pParm;
for (int i = 0; i < st; ++i)
{
if (pDiff & (1 << i))
{
cur = gSparseTable[i][cur];
}
}
return cur;
};
int FindLCA(int pA, int pB, int pN)
{
int H = 0;
while (pN > 1)
{
pN /= 2;
H++;
}
if (pA != pB)
{
for (int i = H; i >= 0; --i)
{
if(gSparseTable[i][pA]!=0 && gSparseTable[i][pA]!= gSparseTable[i][pB])
{
pA = gSparseTable[i][pA];
pB = gSparseTable[i][pB];
}
}
return gSparseTable[0][pA];
}
else
{
return pA;
}
}
int main(void)
{
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
memset(gDepth, -1, sizeof(gDepth));
// root = 1
int n; cin >> n;
for (int i = 0; i < n - 1; ++i)
{
int a, b;
cin >> a >> b;
gLink[a].push_back(b);
gLink[b].push_back(a);
}
DFS(1, 0);
LCA(n);
int m; cin >> m;
for (int i = 0; i < m; ++i)
{
int a, b;
cin >> a >> b;
int aDiff = 0;
if (gDepth[a] != gDepth[b])
{
if (gDepth[a] < gDepth[b]) // a๊ฐ b๋ณด๋ค ์์ ์๋ค.
{
aDiff = gDepth[b] - gDepth[a];
b = aFindDepth(b, aDiff);
}
else
{
aDiff = gDepth[a] - gDepth[b];
a = aFindDepth(a, aDiff);
}
}
cout << FindLCA(a, b, n) << "\n";
}
return 0;
}
![](https://t1.daumcdn.net/keditor/emoticon/niniz/large/010.gif)
'๐ coding test > โฝ ๋ฐฑ์ค' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
(๋ฐฑ์ค/ C++) 1106 - ํธํ / ๋ค์ด๋๋ฏน ํ๋ก๊ทธ๋๋ฐ (0) | 2024.07.11 |
---|---|
(๋ฐฑ์ค/ C++) 2629 - ์ํ์ ์ธ (0) | 2024.07.09 |
(๋ฐฑ์ค/C++) ๊ฐ์ฅ ๊ธด ์ฆ๊ฐํ๋ ๋ถ๋ถ ์์ด 1(11053), 2(12015), 3(12738), 4(14002), 5(14003) ๋ชจ๋ ํ๊ธฐ (0) | 2023.01.18 |
(๋ฐฑ์ค/ C++) 1450 - ๋ ์๋ฌธ์ , ์ด๋ถ ํ์ ์์ ํ์ ๊ทธ๋ ค๋ณด์! (0) | 2023.01.12 |
(๋ฐฑ์ค/ C++) 2470 - ๋ ์ฉ์ก (0) | 2022.09.06 |
์ ํ๋ ๊ฒ ๋ณด๋ค ๋ซ๊ฒ ์ง
ํฌ์คํ ์ด ์ข์๋ค๋ฉด "์ข์์โค๏ธ" ๋๋ "๊ตฌ๋ ๐๐ป" ํด์ฃผ์ธ์!