{"id":26758806,"url":"https://github.com/ham-zettt/competitiveprogramming","last_synced_at":"2025-06-20T00:04:40.759Z","repository":{"id":165602867,"uuid":"556818955","full_name":"ham-zettt/CompetitiveProgramming","owner":"ham-zettt","description":"My solution in CP Problems","archived":false,"fork":false,"pushed_at":"2024-07-26T08:13:10.000Z","size":6024,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-28T16:46:53.010Z","etag":null,"topics":["coding-challenge","competitive-programming","programming-contests"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ham-zettt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-24T15:15:21.000Z","updated_at":"2024-07-26T08:13:14.000Z","dependencies_parsed_at":"2023-07-19T13:00:19.651Z","dependency_job_id":"ca1b66b3-3462-41da-87bd-da05cb62a976","html_url":"https://github.com/ham-zettt/CompetitiveProgramming","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ham-zettt/CompetitiveProgramming","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ham-zettt%2FCompetitiveProgramming","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ham-zettt%2FCompetitiveProgramming/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ham-zettt%2FCompetitiveProgramming/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ham-zettt%2FCompetitiveProgramming/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ham-zettt","download_url":"https://codeload.github.com/ham-zettt/CompetitiveProgramming/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ham-zettt%2FCompetitiveProgramming/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260852095,"owners_count":23072587,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coding-challenge","competitive-programming","programming-contests"],"created_at":"2025-03-28T16:47:05.857Z","updated_at":"2025-06-20T00:04:35.500Z","avatar_url":"https://github.com/ham-zettt.png","language":"C++","readme":"punya gua!\n\n-ilhamz\n\n# Rangkuman Competitive Programming\n\n\u003ca id=\"rangkuman-competitive-programming\"\u003e\u003c/a\u003e\n\n* [Rangkuman Competitive Programming](#rangkuman-competitive-programming)\n  * [Brute Force](#brute-force)\n    * [Permutasi](#brute-force-permutasi)\n      * [Kombinasi](#brute-force-kombinasi)\n  * [Greedy](#greedy)\n  * [Dynamic Programming](#dp)\n    * [Konsep DP](#konsep-dp)\n    * [Contoh Problem DP](#contoh-problem-dynamic-programming)\n      * [Longest Increasing Subsequence (LIS)](#lis)\n      * [Coin Change](#coin-change)\n      * [Path Counting](#path-counting)\n      * [0/1 Knapsack Problem](#knapsack-problem)\n      * [Longest Common Subsequence (LCS)](#lcs)\n  * [Graph](#graph)\n    * [Depth-First Searh (DFS)](#dfs)\n    * [Breadth-First Search (BFS)](#bfs)\n    * [Path Counting pada Graph](#path-counting-graph)\n\n\u003cbr\u003e\n\n## Brute Force\n\n\u003ca id=\"brute-force\"\u003e\u003c/a\u003e\n\nsuatu strategi dengan cara **mecoba semua kemungkinan** (complete search). Sehingga pasti menemukan solusi yang diharapkan, tetapi memiliki waktu yang relatif lama.\n\nContoh persoalan:\n\n\u003e Diberikan sebuah persamaan: p+q+r = 0. Masing-masing dari p, q, dan r harus merupakan anggota dari {a1,a2,...,aN}. Diketahui pula bahwa semua nilai {a1,a2,...,aN}\n\u003e unik. Berapa banyak triplet hp,q,ri berbeda yang memenuhi persamaan tersebut?\n\nSolusi Brute Force:\nCoba semua kemungkinan dengan menggunakan perulangan sebanyak n (banyaknya variabel). Karena n=3, maka waktu kompleksitasnya $O(n^3)$\n\n- Algoritma dapat doptimasi dengan cara: setelah menentukan nilai p dan q, tentukan nilai r dengan -(p+q). Lalu tentukan apakah nilai r ada di anggota himpunan dengan menggunakan binary search agar lebih cepat. Jika ada maka sudah pasti bernilai 0, jadi simpan hasil dari p+q+r. Waktu kompleksitasnya $O(n^2 log n)$\n\n### \u003e Brute Force Permutasi\n\n\u003ca id=\"brute-force-permutasi\"\u003e\u003c/a\u003e\n\nUntuk menampilkan semua permutasi bisa menggunakan iterasi biasa, tetapi jumlah iterasi tidak bisa ditentukan, karena mengikuti jumlah data (n). Maka solusinya adalah rekursif:\n\n```cpp\nchar catat[n];\nbool pernah[n];  // all false\n\nvoid permutation(int depth){\n    // base case\n    if(depth == n){\n          for(int i=0; i\u003cn; i++){    // loop hasil akhir\n            cout \u003c\u003c catat[i];\n        }\n        cout \u003c\u003c endl;\n\n    } else {\n        for(int i=0; i\u003cn; i++){\n            // sebelum masuk ke rekursif, cek apakah\n            // karakter sudah pernah digunakan. Agar\n            // tidak ada digit berulang\n            if(!pernah[i]){\n                pernah[i] = true;\n                catat[depth] = arr[i];  // catat hasil permutasi\n                permutation(depth + 1);\n                pernah[i] = false;  // reset untuk depth lainnya\n            }\n        }\n    }\n}\n```\n\nDimulai dari `permutation(0)`, dari situ akan bercabang sebanyak n, dan seterusnya.\n\n### \u003e Brute Force Kombinasi\n\n\u003ca id=\"brute-force-kombinasi\"\u003e\u003c/a\u003e\n\nuntuk melakukan kombinasi, cukup mengubah perulangan for pada bagian rekursi. Ubah agar perulangan dimulai dari _angka yang dicatat + 1_. Jadi angka sebelumnya tidak akan dicatat lagi. Sehingga _boolean pernah_ tidak perlu dipakai\n`i = catat[depth-1] + 1`\n\n## Greedy\n\n\u003ca id=\"greedy\"\u003e\u003c/a\u003e\n\nsuatu strategi dengan **mencari solusi paling optimal hingga ke subproblem**, sehingga memiliki waktu eksekusi yang cepat dan mudah diimplementasikan. \n\nGreedy dapat dilakukan saat:\n\n- Solusi optimal dapat ditentukan dari subproblem\n- Memiliki _Greedy Choice_\n\n**Greedy choice** merupakan langkah yang akan menghasilkan solusi optimal. Contoh: \n\n\u003e Anda ingin menukar uang Rp12.000 dengan lembaran uang kertas Rp5.000,\n\u003e Rp2.000, dan Rp1.000. Anda ingin menukar dengan jumlah lembaran sesedikit\n\u003e mungkin.\n\n- Problem: proses penukaran uang (n)\n- Subproblemnya: proses penukaran selanjutnya setelah menukar uang ke-n\n- Greedy choice-nya: menukar uang dengan nominal sebesar mungkin\n\nPersoalan tersebut dapat dilakukan dengan Greedy karena terdapat subproblem yag juga dapat ditentukan greedy choicenya.\n\n**Kelemahan Greedy**\nTidak semua persoalan dapat diselesaikan dengan Greedy. Sesuai persoalan diatas, jika uang yang tersedia untuk ditukar adalah Rp5.000, Rp4.000, dan Rp1.000 , maka Greedy tidak memberikan solusi optimal\n\n- Solusi Greedy:  Rp5.000, Rp5.000, Rp1.000, Rp1.000\n- Solusi optimal:  Rp4.000, Rp4.000, Rp4.000\n\n## Dynamic Programming\n\n\u003ca id=\"dp\"\u003e\u003c/a\u003e\n\nMirip dengan brute force tetapi lebih dioptimasi. Masalah yang akan diselesaikan harus memiliki subproblem, lalu akan dicoba satu-persatu.\n\n### Konsep DP\n\n\u003ca id=\"konsep-dp\"\u003e\u003c/a\u003e\n\n- **_Top-Down_**.\n  Metode ini dikerjakan secara rekursif dari problem utama menuju subproblem lainnya. Catat nilai yang sudah dihitung (memoisasi) \n\n- **_Bottom-Up_**.\n  Metode ini dikerjakan secara iteratif dari subproblem menuju problem utama. Hasil perhitungan subproblem akan dicatat didalam array _dp[ ]_.\n\n### Contoh Problem Dynamic Programming:\n\n\u003ca id=\"contoh-problem-dp\"\u003e\u003c/a\u003e\n\n#### Longest Increasing Subsequence (LIS)\n\n\u003ca id=\"lis\"\u003e\u003c/a\u003e\n\n\u003e Carilah subsequence angka terpanjang secara ascending dari [3,1,8,2,5] !\n\n::Jawaban: 2::\n\n_Subproblem_: pemilihan angka LIS, dengan LIS[i] = banyaknya LIS dari indeks ke 0 sampai i\n\nJadi untuk mencari LIS dari awal hingga akhir, maka carilah LIS[4] (terakhir). \n![](.img/lis.png)\n\nDengan metode **Bottom Up**, LIS[i] dapat diselesaikan dengan cara mencari nilai maksimal dari setiap LIS sebelumnya, lalu ditambah satu untuk menghitung LIS ke i sendiri\n\n```cpp\nLIS[i] = max(LIS[0], LIS[1], ..., LIS[n]) + 1\n```\n\n**Algoritma Penyelesaian :**\n\n1. Gunakan outer loop untuk mengisi LIS[i] dari 1 hingga n, sekaligus menjalankan nilai arr[i] untuk dibandingkan\n2. Gunakan inner loop untuk cek setiap LIS sebelum i\n3. Jika `arr[i] \u003e arr[j]` maka LIS[i] **ditambah satu**, karena arr[j] juga termasuk Increasing Subsequence. Jika tidak maka biarkan.\n4. Simpan nilai kedalam LIS[i]\n\n```cpp\nint dp[n];  // array LIS dengan nilai awal 0\nint ans = 0  // untuk mencari Longest\n\ndp[0] = 0;   // base case\n\nfor(int i=1; i\u003cn; i++){\n  int maxx = 0;\n  for(int j=0; j\u003ci; j++){\n    if(arr[i] \u003e arr[j]){\n      maxx = max(dp[j] + 1, dp[i]);\n    } else {\n      maxx = max(dp[j], dp[i]);\n    }\n  } \n  dp[i] = maxx;\n  // untuk mendapatkan Longest, simpan nilai LIS max\n  ans = max(ans, dp[i])\n}\n```\n\n#### Coin Change\n\n\u003ca id=\"coin-change\"\u003e\u003c/a\u003e\n\n\u003e Diberikan 3 jenis koin yaitu [1,6,10] yang jumlahnya tak terbatas. Tentukan banyaknya koin minimal yang bisa ditukar dengan $12$ rupiah\n\n::Jawaban: 2::\n\n- _Subproblem:_ $dp[i]$ adalah penukaran uang sebanyak $n-dp[j]$\n- _Base Case_: saat uang bernilai 0, maka tidak ada koin yang ditukar (return 0)\n\n```cpp\nint dp[n+1];\ndp[0] = 0;\n\nfor(int i=1; i\u003c=n; i++){\n    int minn = 1e5;\n    for(int j=0; j\u003cm; j++){\n        if(i \u003e= coin[j]){\n            minn = min(minn, dp[i-coin[j]] + 1);\n        }\n    }\n    dp[i] = minn;\n}\n```\n\n**Selengkapnya ada di Buku TOKI Competitive Programming**\n\n#### Path Counting\n\n\u003ca id=\"path-counting\"\u003e\u003c/a\u003e\n\n\u003e Hitunglah total jalur dari _start_ menuju _end_, jika gerakan yang diperbolehkan hanya ke bawah dan ke kanan\n\n::Jawaban: 2::\n\n![](.img/path-counting.jpg)\n\n- _Subproblem:_ dp[i][j] adalah banyak jalur yang bisa ditempuh dari start ke petak [i][j]\n- _Base case:_ jumlah jalur pada titik start adalah 1 (return 1)\n\nDengan metode **Bottom Up**, gunakan dp[r][c] untuk mencatat subproblem. Semua petak yang belum dicek bernilai 0 pada tabel dp. Tabel dp[i][j] dapat ditentukan dengan backtracking, yaitu menjumlahkan semua jalur yang ada dipetak kiri dan atas.\n\n```cpp\nif(dp[i-1][j] not out of bounds) dp[i][j] += dp[i-1][j]\nif(dp[i][j-1] not out of bounds) dp[i][j] += dp[i][j-1]\n```\n\n**Algoritma Penyelesaian :**\n\n1. Gunakan outer loop dan inner loop untuk mengisi dp[i][j]\n2. Counter problem saat cek data out of bounds\n\n```cpp\n// isi semua dp dengan 0\n\ndp[0][0] = 1;\nfor(int i=0; i\u003cn; i++){\n    for(int j=0; j\u003cn; j++){\n         // asumsikan jalur yang tersedia adalah bernilai 1\n        if(path[i][j] == 1 \u0026\u0026 (i\u003e0 || j\u003e0)){\n            if(i-1 \u003e= 0 \u0026\u0026 path[i-1][j] != 0) dp[i][j] += dp[i-1][j];\n            if(j-1 \u003e= 0 \u0026\u0026 path[i][j-1] != 0) dp[i][j] += dp[i][j-1];\n        }\n    }\n}\n\ncout \u003c\u003c dp[n-1][n-1];\n```\n\n#### 0/1 Knapsack Problem\n\n\u003ca id=\"knapsack-problem\"\u003e\u003c/a\u003e\n\n\u003e Diberikan N buah barang. Barang ke-i memiliki harga vi rupiah dan berat wi gram. Kita memiliki tas yang berkapasitas C gram. Kita ingin\n\u003e memasukkan beberapa barang ke dalam tas, sehingga dihasilkan harga sebanyak mungkin!\n\n![dawae](.img/knapsack.png)\n\n::Jawaban: 15::\n\nUntuk menyelesaikannya dibutuhkan $dp[i][c]$. Dimana $i$ menyatakan jumlah barang yang tersedia dari barang ke-1 sampai i. Dan $j$ menyatakan kapasitas tas dimulai dari 0\n\nTerdapat 2 pilihan, yaitu **ambil** barang atau **tidak**. Saat barang diambil maka $i$ akan berkurang 1 dan mendapatkan harga barang tersebut. Saat barang tidak diambil, maka $i$ juga berkurang 1 karena barang diskip. Tetapi tidak mendapatkan harga. Dapat dituliskan sebagai berikut:\n\n```cpp\nambil = dp[i-1][c - wi] + vi\nnotAmbil = dp[i-1][c]\n```\n\n- _Subproblem:_ $dp[i][j]$ adalah harga maksimal saat tersedia barang 1 sampai i, dan kapasitas tas sebanyak j gram\n- _Base case:_ Saat kapasitas tas 0 gram, maka tidak ada barang yang bisa dimasukkan (return 0)\n\n**Algoritma penyelesaian:**\n\n1. Isi semua $dp[i][0]$ dengan 0 sebagai base case.\n2. Gunakan outer loop untuk mengisi $i$ sebagai banyak barang yang akan dicek, dan inner loop untuk mengisi $j$ dimulai dari 1 sampai tepat $c$\n3. Counter problem saat $i-1 \u003c 0$ karena akan out of bounds.\n\n```cpp\nint dp[n][c+1];\nfor(int i=0; i\u003cn; i++) dp[i][0] = 0;  // base case\n\nfor(int i=0; i\u003cn; i++){\n    int ambil=0, notAmbil=0;\n    for(int j=1; j\u003c=c; j++){\n\n        // counter problem saat i = 0\n        if(i == 0){\n            if(j \u003e= pr[i].second){    // ambil\n                dp[i][j] = pr[i].first;\n            } else {    // tidak ambil\n                dp[i][j] = 0;\n            }\n\n        } else {\n            if(j \u003e= pr[i].second){\n                ambil = dp[i-1][j-pr[i].second] + pr[i].first;\n            }\n            notAmbil = dp[i-1][j];\n            dp[i][j] = max(ambil, notAmbil);\n        }\n    }\n}\n\ncout \u003c\u003c dp[n-1][c+1-1];\n```\n\n#### Longest Common Subsequence (LCS)\n\n\u003ca id=\"lcs\"\u003e\u003c/a\u003e\n\n\u003e Diberikan 2 buah string A dan B. Panjang kedua string tidak harus sama. Berapa\n\u003e panjang string terpanjang yang merupakan subsequence dari A dan B? \u003cbr\u003e A = \"ajaib\" \u003cbr\u003e B = \"badai\"\n\n::Jawaban: 3 (aai)::\n\nGunakan konsep _character cutoff_ mulai dari subproblem terkecil, yaitu saat hanyan tersedia 1 character pada masing-masing string (A=\"a\", B=\"b\"). Lalu meningkat sampai tersedia semua karakter.\n\nGunakan $dp[i][j]$, dimana $i$ merupakan jumlah karakter yang tersedia untuk A dari indeks 0 sampai $i$. Dan begitu juga $j$ untuk B.\n\nTerdapat 2 kondisi, yaitu ketika karakter sama dan tidak sama.\n\n- Jika $A[i] == B[j]$, maka LCS ditambah 1. Karena karakter sama, maka kita dapat melanjutkan cek ke karakter sebelumnya (backtracking).\n- Jika $A[i] ≠  B[j]$, maka coba cek $A[i]$ dengan $B[j-1]$ dan $B[j]$ dengan $A[i-1]$ _(character cutoff)_. Dan cari LCS maksimalnya.\n\n```cpp\nif(A[i] == B[i]){\n  dp[i][j] = dp[i-1][j-1] + 1;\n} else{\n  cutA = dp[i-1][j];\n  cutB = dp[i][j-1];\n  dp[i][j] = max(cutA, cutB);\n}\n```\n\n- _Subproblem:_ $dp[i][j]$ adalah LCS saat A hanya tersedia karakter 0 sampai $i$. Dan B hanya tersedia karkter 0 sampai $j$\n- _Basecase:_ Saat $i=0$ atau $j=0$ maka tidak bisa mendapatkan subsequence, karena tidak ada karakter. (return 0)\n\n```cpp\n    string a = \"ajaib\";\n    string b = \"badai\";\n    int m = a.length();\n    int n = b.length();\n\n    int dp[m+1][n+1];\n     for(int i=0; i\u003c=m; i++) dp[i][0] = 0;  //basecase\n    for(int i=0; i\u003c=n; i++) dp[0][i] = 0;  //basecase\n\n    for(int i=1; i\u003c=m; i++){\n        for(int j=1; j\u003c=n; j++){\n            if(a[i-1] == b[j-1]){  // -1 karena cek indeks dari 0\n                dp[i][j] = dp[i-1][j-1] + 1;\n            } else {\n                int cutA = dp[i][j-1]; \n                int cutB = dp[i-1][j];\n                dp[i][j] = max(cutA, cutB);\n            }\n        }\n    }\n```\n\n## Graph\n\n\u003ca id=\"graph\"\u003e\u003c/a\u003e\n\n### Representasi Graph\n\n- **Adjenct List**\n  \n  Masing-masing node disimpan dalam array. Setiap index array menyimpan vector berisi node yang terhubung\n  \n  ```cpp\n  // untuk graf tidak berbobot\n  vector\u003cint\u003e adj[N];\n  adj[1].push_back(3); //node1 ke node3\n  adj[2].push_back(1);\n  adj[4].push_back(2); \n  \n  // untuk graf berbobot\n  vector\u003cpair\u003cint,int\u003e\u003e adj[N];\n  adj[1].push_back({4,5});\n  adj[2].push_back({2,1});\n  adj[4].push_back({4,2});\n  ```\n\n- **Adjency Matix**\n  Baris untuk node, dan kolom untuk node tujuan. Value matriks berisi nilai boolean yang menandakan node terhubung atau tidak\n  \n  ```cpp\n  int adj[N][N];\n  adj[1][2] = 1;\n  adj[3][1] = 1;\n  ```\n\n- **Edge List**\n  \n  Node yang terhubung disimpan didalam vector, tanpa berpatokan indeks.\n  \n  ```cpp\n  vector\u003cint\u003e adj;\n  adj.push_back({2,3})\n  adj.push_back({1,2})\n  ```\n\n### DFS (Depth-First Search)\n\n\u003ca id=\"dfs\"\u003e\u003c/a\u003e\n\nAdalah konsep traversal pada graph yang **memprioritaskan node paling dalam terlebih dahulu**. Langkah yang dilakukan dalam penelusuran DFS:\n\n1. Push node awal kedalam stack\n2. Telusuri tetangga node yang belum dikunjungi, lalu push kedalam stack. Node yang masuk akan menjadi prioritas, sehingga node pada stack sebelumnya harus menunggu dulu. **(prioritaskan node terdalam)**\n3. Sekaligus tandai node yang masuk kedalam stack sebagai node yang sudah dikunjungi\n4. Ulangi sampai semua node terkunjungi\n\n```cpp\n    stack\u003cint\u003e st;    // simpan node yang belum dikunjungi\n    bool visited[n+1];    // sudah/belum dikunjungi\n\n    // fill\n    fill(visited, visited+n+1, false);\n\n    st.push(1);\n    visited[1] = true;\n    while(!st.empty()){\n        int current = st.top();\n        st.pop();\n        cout \u003c\u003c \"node-\" \u003c\u003c current;\n\n        for(int i=1; i\u003c=n; i++){    // cari semua node tetangga yg belum dikujungi\n            if(jalur[current][i] \u0026\u0026 !visited[i]){\n                st.push(i);\n                visited[i] = true;    // setelah ditemukan, langsung tandai\n            }\n        }    \n    }    \n```\n\n### BFS (Breadth-First Search)\n\n\u003ca id=\"bfs\"\u003e\u003c/a\u003e\n\nKonsep traversal pada graph yang **memprioritaskan node terdekat**. Langkah yang dilakukan dalam penelusuran BFS:\n\n\u003e BFS tidak dapat dilakukan dengan rekursif\n\n1. Push node awal kedalam queue\n2. Telusuri tetangga node yang belum dikunjungi, lalu push kedalam queue. Node tersebut akan dikunjungi setelah semua node sebelumnya terkunjungi\n3. Sekaligus tandai node yang masuk kedalam queue sebagai node yang sudah dikunjungi\n4. Ulangi sampai semua node terkunjungi\n\n```cpp\n    queue\u003cint\u003e q;\n    bool visited[n+1];\n\n    fill(visited, visited+n+1, false);\n\n    q.push(1);\n    visited[1] = true;\n    while(!q.empty()){\n        int current = q.front();\n        q.pop();\n        cout \u003c\u003c \"node-\" \u003c\u003c current;\n\n        for(int i=1; i\u003c=n; i++){\n            if(jalur[current][i] \u0026\u0026 !visited[i]){\n                q.push(i);\n                visited[i] = true;\n            }\n        }\n    }\n```\n\n### Path Counting pada Graph\n\n\u003ca id=\"path-counting-graph\"\u003e\u003c/a\u003e\n\nTambahkan array baru untuk menyimpan jarak pada suatu node ke node lainnya. Isi array tersebut saat proses push dengan nilai `jarak[node] = jarak[current] + 1`.\n\nMenggunakan *adjacency list*:\n\n```cpp\nfor(int i: adj[current]){\n    if(!visited[i]){\n        st.push(i);\n        visited[i] = true;\n        dist[i] = dist[current] + 1;\n    }\n}\n```\n\n### Component Count\n\n\u003cimg src=\".img/graph2.png\" title=\"\" alt=\"\" width=\"336\"\u003e\n\nUntuk menghitung berapa komponen pada graf, kita harus memulai traversal dari node pada masing-masing komponen\n\n1. Perulangan dimulai dari $visited[]$ node pertama sampai akhir. Jika belum dikunjungi maka push kedalam stack sebagai start node dari suatu komponen\n\n2. Traversal akan berjalan sambil mencatat node yang dikunjungi dari komponen tersebut\n\n3. Pastikan semua node terkunjungi, jika belum masukkan ke dalam stack dan ulangi langkah ke dua\n\n4. Jika ada lakukan traversal dari node tersebut sebagai  start node\n\n```cpp\nfor(int i=1; i\u003cn+1; i++){ //loop untuk visited[]\n\n\t\tif(!visited[i]){\n\t\t\tans++;\n\t\t\tqu.push(i);\n\t\t\tvisited[i] = true;\n\n\t\t\twhile(!qu.empty()){\n\t\t\t\tint current = qu.front();\n\t\t\t\tcout \u003c\u003c current \u003c\u003c endl;\n\t\t\t\tqu.pop();\n\n\t\t\t\tfor(int i=1; i\u003cn+1; i++){\n\t\t\t\t\tif((adj[current][i] || adj[i][current]) \u0026\u0026 !visited[i]){\n\t\t\t\t\t\tqu.push(i);\n\t\t\t\t\t\tvisited[i] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n```\n\n\n\n---\n\n# Rangkuman C++\n\n## For Your Information\n\n### Print Variable type\n\n```cpp\ncout \u003c\u003c typeid(var).id();\n```\n\n### Prototype function\n\nDeklarasi fungsi disetelah main dapat dilakukan dengan cara membuat prototype:\n\n```cpp\nvoid solve(int a, int b);\nint main(){\n    ...\n}\nvoid solve(int a, int b){\n    ...\n}\n```\n\n### Get single line input\n\n```cpp\ngetline(cin, input);\n```\n\n### _goto_ Function\n\nGo to the spesific flag\n\n```cpp\nflagName:\n  print(\"go to here\");\n\ngoto flagName;\n```\n\n### Determine its decimal or not\n\n```cpp\n#include \u003ccmath\u003e\nif(i/3 == floor(i/3)) isDecimal = false;\n```\n\n### Determine its a perfect square\n\n```cpp\ntemp = round(sqrt(i));\nif(temp*temp == i) isPerfect = true;\n```\n\n### Sort pair based on second (boolean)\n\n```cpp\nbool sort_second(pair\u003cint, int\u003e \u0026a, pair\u003cint, int\u003e \u0026b){\n    return a.second \u003c b.second;\n}\n\nvector\u003cpair\u003cint,int\u003e\u003e pr;\nsort(pr.begin(), pr.end(), sort_second);\n```\n\n### Return array function with pointer\n\n```cpp\nint * generate(int arr[], int size){\n    for(int i=0; i\u003csize; i++){\n        arr[i] = i+1;\n    }\n    return arr;\n}\n\nint main(){\n    int *arr = generate();\n}\n```\n\n## Data Structure Type\n\n### Map\n\nmenyimpan data menurut key dan value nya.\n\n```cpp\nmap\u003cstring, int\u003e mp;\nmp[\"john\"] = 98;\nmp[\"marko\"] = 72;\n\n// loop with iterator\n// first for the key, second for the value\nfor(auto it=mp.begin(); it!=mp.end(); it++){\n    cout \u003c\u003c it-\u003efirst \u003c\u003c \" \" \u003c\u003c it-\u003esecond \u003c\u003c endl;\n}\n```\n\n--- \n\n## Algorithm\n\n### Binary search\n\nPengurutan seperti halnya mencari kata didalam kamus. \nTime complexity: $O(log n)$\n\n```cpp\nmid = 0;\nans = 0;\nleft = 0;\nright = arr.length()-1;\n\nwhile(left\u003c=right and ans==0){\n    mid = (left+right) / 2;\n    if(search\u003carr[mid]) right = mid-1;\n    else if(search\u003earr[mid]) left = mid+1;\n    else ans = arr[mid];\n}\n```\n\n### Sorting with Parameter Function\n\n```cpp\nbool sc(int a, int b){\n    if(a%b != 0) return true;\n    else return false;\n\nint main(){\n    sort(arr, arr+n, sc);\n}\n```\n\n### Print all substring\n\nuse s.substr(start, substring length);\n\n```cpp\nfor(int i=0; i\u003cs.length(); i++){\n        for(int j=1; j\u003c=s.length()-i; j++){\n            cout \u003c\u003c s.substr(i,j) \u003c\u003c endl;\n        }\n    }\n```\n\n### Maximum subarray sum\n\nBasically, it needs 2 iteration. Time complexity: $O(n^2)$\n\n```cpp\nint ans = 0;\nfor(int i=0; i\u003cn; i++){\n  int sum = 0\n  for(int j=i; j\u003cn; j++){\n    sum += arr[j];\n    ans = max(ans, sum);\n  }\n}\n```\n\nAlgorithm with single iteration. Time complexity: $O(n)$\n\n```cpp\nint best = 0, sum = 0;\nfor(int i=0; i\u003cn; i++){\n  sum = max(arr[i], sum+arr[i]);\n  ans = max(ans, sum);\n}\n```\n\n### Prefix Sum\n\nSebuah array yang berisi total setiap elemen array, yang dihitung satu persatu. Contoh [3,4,2,5], prefix-sumnya adalah [3,7,9,14]\n\n```cpp\nint ps[n];\nps[0] = arr[0];  //nilai pertama\nfor(int i=1; i\u003cn; i++){\n  ps[i] = arr[i] + ps[i-1];\n}\n```\n\nAtau gunakan fungsi dari STL:numeric partial_sum\n\n```cpp\nint arr[] = {1,2,3}, ps[n];\npartial_sum(arr, arr+n, ps[n]) //hasil akan disimpan di array ps\n```\n\nUntuk mengakses jumlah subarray $l$ sampai $r$, gunakan perhitungan:\n\n```cpp\nint subarray = ps[r] - ps[l-1]\n```\n\n## STRING\n\n### Uppercase and lowercase\n\n```cpp\n//to check\nisupper(c)\nislower(c)\n//to convert\ntoupper(c)\ntolower(c)\n```\n\n### Convert string \u003c-\u003e integer\n\n```cpp\nstoi(s);  // string to integer\nto_string(i);  // integer to string\n```\n\n### Erase a character from string\n\n```cpp\ns.erase();      // erase all\ns.erase(2);     // erase from index 2 \ns.erase(2, 4);  // earse from index 2, up to 4 character\n```\n\n## ARRAY\n\n### Array summary\n\n```cpp\naccumulate(arr, arr+arrLength, sum)\n```\n\n### Fill array\n\n```cpp\n#include \u003ccstring\u003e\nmemset(arr, 0, sizeof(arr))  //set the memory\nfill()\n```\n\n### Sort array ascending/descending\n\n```cpp\n#include \u003calgorithm\u003e\nsort(arr, arr+n); //ascending\nsort(arr, arr+n, greater\u003cint\u003e()); //descending\nsort(arr, arr+n, greater\u003cdouble,int\u003e()); //descending (pair)\n```\n\n### How many element types in array\n\n```cpp\nint count = 0;\nbool isUnique = true\n\nfor(int i=0; i\u003cn; i++){\n    for(int j=i+1; j\u003cn; j++){\n        if(arr[i] == arr[j]){\n            isUnique = false;  //same element detected\n            break;\n    }\n\n    if(isUnique) count++;\n}\n```\n\n### Find an element in array\n\n```cpp\nif(find(begin(arr), end(arr), \"a\") != end(arr)){\n  // Element found\n}\n```\n\n### Check all of the array element\n\n```cpp\n#include \u003calgorithm\u003e\nif(all_of(begin(arr), end(arr), [](bool b){return b==true};)){\n    isAllTrue = true;\n}\n```\n\n### Permutation\n\n```cpp\n#include \u003calgorithm\u003e\nnext_permutation(begin(arr), end(arr));\n```\n\n## VECTOR\n\n### Function\n\n```cpp\n// initialize with size and value \nvector\u003cint\u003e vt(10, 0);  // size=10; element=0\n\n// get vector size\nint n = vt.size();\n\n// modify element\nvt.push_back()  //add element\nvt.pop_back()   //remove last element\nvt.insert(vt.begin() + (indexTarget) , value)   //insert at index\nvt.clear()   //erase all element\nvt.erase(vt.begin + (indexTarget))   //erase at index\nvt.empty()   //check empty\n```\n\n## FUNCTION\n\n### Reverse number\n\n```cpp\nrev = 0\nwhile(num\u003e0){\n    rev = (rev*10) + (num%10);\n    num /= 10;\n}\n```\n\n### Prime number\n\n```cpp\nint n; //angka yang dicek\nbool isPrime = true;\n\nfor(int i=2; i*i\u003c=n; i++){\n    if(n%i == 0){\n        isPrime = false;\n        break;\n    }\n}\n\nif(isPrime) cout \u003c\u003c \"Prime\";\nelse cout \u003c\u003c \"Not Prime\";\n```\n\n### GCD with Euclid Method\n\n```cpp\nint euclid(int a, int b){\n    if(b==0) return a;\n        else return euclid(b, a%b);\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fham-zettt%2Fcompetitiveprogramming","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fham-zettt%2Fcompetitiveprogramming","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fham-zettt%2Fcompetitiveprogramming/lists"}