# 期末程式 # Min Heap 插入節點 ``` #include <stdio.h> #include <stdlib.h> #define MXN 200005 void insert_heapify(int* v, int x) { if (x <= 0) return; // 如果是root 結束遞迴 int f = (x - 1) / 2; // 父節點索引 if (v[x] < v[f]) { // 當前節點小於父節點 交換並繼續檢查 int temp = v[x]; v[x] = v[f]; v[f] = temp; insert_heapify(v, f); } } void solve() { int* v = (int*)malloc(MXN * sizeof(int)); if (!v) { fprintf(stderr, "Memory allocation failed\n"); return; } int cnt = -1; int u; while (scanf("%d", &u) != EOF) { v[++cnt] = u; insert_heapify(v, cnt); for (int i = 0; i <= cnt; i++) { printf("[%d]%d ", i + 1, v[i]); } printf("\n"); } free(v); } int main() { solve(); return 0; } ``` # 二元搜尋樹刪除節點 ``` #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct TreeNode { int data; struct TreeNode* left; struct TreeNode* right; } TreeNode; TreeNode* createNode(int value) { TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode)); newNode->data = value; newNode->left = NULL; newNode->right = NULL; return newNode; } TreeNode* insert(TreeNode* root, int value) { if (root == NULL) { return createNode(value); } if (value < root->data) { root->left = insert(root->left, value); } else if (value > root->data) { root->right = insert(root->right, value); } return root; } void preorder(TreeNode* root) { if (root != NULL) { printf("%d ", root->data); preorder(root->left); preorder(root->right); } } TreeNode* findMax(TreeNode* root) { while (root->right != NULL) { root = root->right; } return root; } TreeNode* deleteNode(TreeNode* root, int key, int* found) { if (root == NULL) { return NULL; } if (key < root->data) { root->left = deleteNode(root->left, key, found); } else if (key > root->data) { root->right = deleteNode(root->right, key, found); } else { *found = 1; // 無子節點 if (root->left == NULL && root->right == NULL) { free(root); return NULL; } if (root->left == NULL) { TreeNode* temp = root->right; free(root); return temp; } else if (root->right == NULL) { TreeNode* temp = root->left; free(root); return temp; } // 有兩個子節點:用左子樹中最大值取代 TreeNode* maxNode = findMax(root->left); root->data = maxNode->data; root->left = deleteNode(root->left, maxNode->data, found); } return root; } int main() { TreeNode* root = NULL; int value; char line[1000]; fgets(line, sizeof(line), stdin); char* token = strtok(line, " "); while (token != NULL) { value = atoi(token); root = insert(root, value); token = strtok(NULL, " "); } printf("Binary search tree (before):\n"); preorder(root); printf("\n"); fgets(line, sizeof(line), stdin); token = strtok(line, " "); while (token != NULL) { value = atoi(token); int found = 0; root = deleteNode(root, value, &found); if (!found) { printf("no %d\n", value); } token = strtok(NULL, " "); } printf("Binary search tree (after):\n"); preorder(root); printf("\n"); return 0; } ``` # MIN HEAP 刪除節點 ``` #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define MXN 200005 // 插入操作的堆调整 void insert_heapify(int v[], int x) { if (x == 0) return; int f = (x - 1) >> 1; // 父节点索引 if (v[x] < v[f]) { int temp = v[x]; v[x] = v[f]; v[f] = temp; insert_heapify(v, f); } } void delete_heapify(int v[], int n, int x) { int smallest = x; int l = (x << 1) + 1; // 左子节点索引 int r = (x << 1) + 2; // 右子节点索引 if (l < n && v[l] < v[smallest]) smallest = l; if (r < n && v[r] < v[smallest]) smallest = r; if (smallest != x) { int temp = v[x]; v[x] = v[smallest]; v[smallest] = temp; delete_heapify(v, n, smallest); } } void solve() { int* v = (int*)malloc(MXN * sizeof(int)); if (!v) { fprintf(stderr, "Memory allocation failed for heap array\n"); return; } char* input = (char*)malloc(MXN * 10 * sizeof(char)); if (!input) { fprintf(stderr, "Memory allocation failed for input buffer\n"); free(v); return; } int cnt = -1; if (fgets(input, MXN * 10, stdin) == NULL) { free(v); free(input); return; } int num = 0, in_number = 0; for (char* p = input; *p != '\0'; p++) { if (isdigit(*p)) { num = num * 10 + (*p - '0'); in_number = 1; } else if (in_number) { v[++cnt] = num; insert_heapify(v, cnt); num = 0; in_number = 0; } } if (in_number) { v[++cnt] = num; insert_heapify(v, cnt); } for (int i = 0; i <= cnt; i++) { printf("[%d]%d ", i + 1, v[i]); } printf("\n"); while (cnt >= 0) { v[0] = v[cnt]; cnt--; delete_heapify(v, cnt + 1, 0); for (int i = 0; i <= cnt; i++) { printf("[%d]%d ", i + 1, v[i]); } printf("\n"); } free(v); free(input); } int main() { solve(); return 0; } ``` ![image](https://hackmd.io/_uploads/B1Ox0Z8myg.png) ![image](https://hackmd.io/_uploads/BJsWRZ871l.png) # Almost Union-Find ``` #include <stdio.h> #define MAX 200001 long long sum[MAX]; int par[MAX], r[MAX], coor[MAX]; // 查找并查集的根 int searchroot_(int x) { if (par[x] != x) { par[x] = searchroot_(par[x]); } return par[x]; } // 合并两个集合 void unite(int x, int y) { x = searchroot_(x); y = searchroot_(y); if (x == y) { return; } if (r[x] < r[y]) { par[x] = y; sum[y] += sum[x]; r[y] += r[x]; } else { par[y] = x; sum[x] += sum[y]; r[x] += r[y]; } } int main() { int n, com; while (scanf("%d %d", &n, &com) != EOF) { for (int i = 1; i <= n + com; i++) { par[i] = i; r[i] = 1; sum[i] = i; coor[i] = i; } int c, in1, in2; while (com--) { scanf("%d %d", &c, &in1); if (c == 1) { scanf("%d", &in2); unite(coor[in1], coor[in2]); } else if (c == 2) { scanf("%d", &in2); int par1 = searchroot_(coor[in1]); int par2 = searchroot_(coor[in2]); if (par1 != par2) { sum[par1] -= in1; r[par1]--; n++; coor[in1] = n; par[n] = n; sum[n] = in1; r[n] = 1; unite(coor[in1], coor[in2]); } } else if (c == 3) { int p = searchroot_(coor[in1]); printf("%d %lld\n", r[p], sum[p]); } } } return 0; } ``` ![image](https://hackmd.io/_uploads/B1XrNlcmkx.png) ![image](https://hackmd.io/_uploads/Hkq8NlqX1x.png) # 相鄰矩陣與相鄰串列 ``` #include <iostream> #include <vector> #include <algorithm> #include <map> using namespace std; #define MXN 10005 // 稀疏鄰接矩陣 map<int, map<int, int>> board; // 鄰接表 vector<int> edge[MXN]; void solve() { int u, v, mx = -1; while (cin >> u >> v) { // 忽略自環 if (u == v) continue; board[u][v] = 1; board[v][u] = 1; if (find(edge[u].begin(), edge[u].end(), v) == edge[u].end()) { edge[u].push_back(v); } if (find(edge[v].begin(), edge[v].end(), u) == edge[v].end()) { edge[v].push_back(u); } mx = max({mx, u, v}); } cout << "Adjacency matrix:\n"; for (int i = 0; i <= mx; i++) { for (int j = 0; j <= mx; j++) { cout << (board[i][j] ? 1 : 0) << " \n"[j == mx]; } } cout << "\nAdjacency list:\n"; for (int i = 0; i <= mx; i++) { cout << i << ": "; sort(edge[i].begin(), edge[i].end()); for (int j : edge[i]) { cout << j << " -> "; } cout << "end\n"; } } int main() { solve(); return 0; } ``` ![image](https://hackmd.io/_uploads/ByI31q-N1e.png) ![image](https://hackmd.io/_uploads/SkB6Jq-Nkl.png) ![image](https://hackmd.io/_uploads/SJl01q-Nkx.png) # 網路連通性 ``` #include <iostream> #include <vector> #include <algorithm> using namespace std; vector<vector<int>> edge; vector<bool> vis; void dfs(int x) { vis[x] = true; for (int i : edge[x]) { if (!vis[i]) { dfs(i); } } } void solve() { int n, x; cin >> n; if (n <= 0) { cout << "-1\n"; return; } edge.assign(n, vector<int>()); vis.assign(n, false); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cin >> x; if (x && i != j) { edge[i].push_back(j); } } } dfs(0); if (count(vis.begin(), vis.end(), true) == n) { cout << "1\n"; } else { cout << "-1\n"; } } int main() { solve(); return 0; } ``` ![image](https://hackmd.io/_uploads/r1ZGbcZEye.png) # DFS 與 BFS ``` #include <iostream> #include<vector> #include<queue> #include <algorithm> using namespace std; #define MXN 100005 vector<int> edge[MXN];//element adjacency list of a vertex vector<bool>vis; vector<int> res1, res2;// store traversal order of vertices for DFS and BFS respectively. void dfs(int x) {/* 從一個點x開始對這個圖的深度優先搜尋 */ vis[x] = true; res1.push_back(x); for (int i : edge[x]) { if (vis[i]) { continue; } dfs(i); } } void solve() { int u, v, mx = -1; while (cin >> u >> v) { edge[u].push_back(v); edge[v].push_back(u); mx = max({ mx, u, v }); } vis.clear(); vis.resize(mx + 1, false); dfs(0); cout << "Depth First Search:\n"; for (int i = 0; i < res1.size(); i++) { cout << res1[i] << " \n"[i == res1.size() - 1]; } vis.clear(); vis.resize(mx + 1, false); queue<int> que; que.push(0); while (!que.empty()) { int x = que.front(); que.pop(); if (!vis[x]) { res2.push_back(x); } vis[x] = true; for (int i : edge[x]) { if (!vis[i]) { que.push(i); } } } cout << "\nBreadth First Search:\n"; for (int i = 0; i < res2.size(); i++) { cout << res2[i] << " \n"[i == res2.size() - 1]; } } int main() { solve(); return 0; } /* Depth First Search: 0 3 1 2 Breadth First Search: 0 3 1 2 */ ``` ![image](https://hackmd.io/_uploads/rJn4vJnEkl.png) ![image](https://hackmd.io/_uploads/HkzzvJhVJx.png) # 計算圖形的 low 與 dfn 值 ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #define MXN 100005 #define MAX_EDGES 200005 typedef struct { int n, step; int dfn[MXN], low[MXN]; int *edge[MXN]; int edgeCount[MXN]; } Solution; Solution graph; void init(Solution *graph, int _n) { graph->n = _n; graph->step = 0; for (int i = 0; i < _n; i++) { graph->edge[i] = malloc(sizeof(int) * MAX_EDGES); graph->edgeCount[i] = 0; graph->dfn[i] = -1; graph->low[i] = -1; } } void addEdge(Solution *graph, int u, int v) { graph->edge[u][graph->edgeCount[u]++] = v; graph->edge[v][graph->edgeCount[v]++] = u; } void dfs(Solution *graph, int x, int f) { graph->dfn[x] = graph->low[x] = graph->step++; for (int i = 0; i < graph->edgeCount[x]; i++) { int next = graph->edge[x][i]; if (next == f) continue; if (graph->dfn[next] == -1) { dfs(graph, next, x); graph->low[x] = (graph->low[x] < graph->low[next]) ? graph->low[x] : graph->low[next]; } else { graph->low[x] = (graph->low[x] < graph->dfn[next]) ? graph->low[x] : graph->dfn[next]; } } } void printSol(Solution *graph) { printf(" "); for (int i = 0; i < graph->n; i++) { printf("%d%s", i, (i == graph->n - 1) ? "\n" : " "); } printf("dfn "); for (int i = 0; i < graph->n; i++) { printf("%d%s", graph->dfn[i], (i == graph->n - 1) ? "\n" : " "); } printf("low "); for (int i = 0; i < graph->n; i++) { printf("%d%s", graph->low[i], (i == graph->n - 1) ? "\n" : " "); } } void solveGraph(Solution *graph) { for (int i = 3; i < graph->n; i++) { if (graph->dfn[i] == -1) { dfs(graph, i, i); } } for (int i = 0; i < 3; i++) { if (graph->dfn[i] == -1) { dfs(graph, i, i); } } printSol(graph); } void solve() { int u, v, mx = -1; int edge[MAX_EDGES][2]; int edgeCount = 0; while (scanf("%d %d", &u, &v) != EOF) { edge[edgeCount][0] = u; edge[edgeCount][1] = v; edgeCount++; mx = (mx > u) ? mx : u; mx = (mx > v) ? mx : v; } init(&graph, mx + 1); for (int i = 0; i < edgeCount; i++) { addEdge(&graph, edge[i][0], edge[i][1]); } solveGraph(&graph); // Free allocated memory for (int i = 0; i < graph.n; i++) { free(graph.edge[i]); } } int main() { solve(); return 0; } ``` ![image](https://hackmd.io/_uploads/HJxoD12NJg.png) ![image](https://hackmd.io/_uploads/Sy1cPk3V1x.png) # 很油的田 ``` #include <stdio.h> #include <stdbool.h> #define MAX 100 // 假设最大网格尺寸为 100x100 int dx[] = { -1, 1, 0, 0, -1, 1, -1, 1 }; int dy[] = { 0, 0, -1, 1, -1, -1, 1, 1 }; void dfs(char grid[MAX][MAX], bool visited[MAX][MAX], int x, int y, int n, int m) { visited[x][y] = true; for (int i = 0; i < 8; i++) { int nx = x + dx[i]; int ny = y + dy[i]; if (nx >= 0 && ny >= 0 && nx < n && ny < m && grid[nx][ny] == '@' && !visited[nx][ny]) { dfs(grid, visited, nx, ny, n, m); } } } int main() { int n, m; while (scanf("%d %d", &n, &m) == 2 && (n || m)) { char grid[MAX][MAX]; bool visited[MAX][MAX] = {false}; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { scanf(" %c", &grid[i][j]); } } int pos = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (grid[i][j] == '@' && !visited[i][j]) { dfs(grid, visited, i, j, n, m); pos++; } } } printf("%d\n", pos); } return 0; } ``` ![image](https://hackmd.io/_uploads/Bk_HdJ3V1l.png)