開啟章節選單
11518 Dominos 2
因為我演算法都習慣用Java寫,所以我多寫了Java的題解,再翻譯成C++,因此本篇有Java與C++的題解
題目敘述
給你n個骨牌,編號1~n 然後給你一個數字k,告訴你k次骨牌a倒下會導致骨牌b倒下 再給你一個數字p,總共要推倒p張骨牌,然後告訴你要推倒哪些骨牌(按順序推倒)(推倒的骨牌不會再立起來) 輸出有多少骨牌被推倒 題目要注意的地方: 骨牌被推倒後,就不會被別的骨牌推倒了,可以用陣列來記錄哪些骨牌被推倒 骨牌有可能一次讓超過一個骨牌倒下
輸入格式
先輸入一個整數S,接下來有S組測資 每一組測資的第一行有三個整數n,k,p n代表n張骨牌,k代表有多少骨牌會壓倒骨牌的關係,p代表要推倒多少骨牌 接下來有k行,每行兩個數字x,y,代表推倒骨牌x時,骨牌y會倒下 接下來有p行,每行一個數字,代表你要推倒的骨牌代號
關鍵知識點
圖遍歷
解題思路
訪問a會導致訪問b,c,d,...,訪問過的東西不會再度訪問 這種情況就跟圖一樣,可以把骨牌關係畫成一個有向圖,接下來就根據推倒的骨牌代號來BFS或DFS就可以了
import java.util.*; public class CPE20240521_5 { static int []check; static int total; static void DFS(Node n) { total++; check[n.data]=1; for(Node e:n.neig) if(check[e.data]==0) DFS(e); } public static void main(String[]args) { Scanner sc=new Scanner(System.in); int S=sc.nextInt(); for(int IT=0;IT<S;IT++) { int n=sc.nextInt(),k=sc.nextInt(),p=sc.nextInt(); check=new int[n]; total=0; Node []arr=new Node[n]; for(int i=0;i<n;i++) arr[i]=new Node(i); for(int i=0;i<k;i++) { int x=sc.nextInt()-1,y=sc.nextInt()-1; arr[x].neig.add(arr[y]); } for(int i=0;i<p;i++) { int j=sc.nextInt()-1; if(check[j]==0) DFS(arr[j]); } System.out.println(total); } } } class Node { List<Node>neig=new ArrayList<>(); int data; public Node(int data) { this.data=data; } }
#include <iostream> #include <vector> using namespace std; class node { public: int data; vector<node*> neig; node(int I = 0) { data = I; } }; static vector<int> check(10000); static int total; void DFS(node* n) { total++; check[n->data] = 1; for (node* e : n->neig) { if (!check[e->data]) DFS(e); } } int main() { int S; cin >> S; while (S--) { int n, k, p; cin >> n >> k >> p; fill(check.begin(), check.end(), 0); total = 0; node arr[10000]; // 開大一點 for (int i = 0; i < n; i++) arr[i] = node(i); while (k--) { int x, y; cin >> x >> y; x--; y--; arr[x].neig.push_back(&arr[y]); } while (p--) { int j; cin >> j; j--; if (!check[j]) DFS(&arr[j]); } cout << total << endl; } }