題目敘述
題目要求設計一個程式,能夠從輸入的圖形資料中,找出一個最小的節點集合,使得圖中每條邊至少有一個端點包含在這個集合內。
輸入資料的格式為:
第一行是一個整數n,代表這個圖形有n個節點(編號從0到n-1)
接下來有n行,每行有n個0或1,用來表示節點之間的連接關係。第i行第j個數字為1,表示節點i和節點j之間有一條邊相連,為0則表示沒有連接。
輸入資料會連續輸入多組圖形,直到出現一個-1作為結束訊號。
程式需要對於每一組輸入的圖形資料,輸出一個整數,代表最小節點覆蓋集合所包含的節點數量。
舉個例子,假設輸入資料為:
代表這個圖形有2個節點(0和1),且這兩個節點之間有一條邊相連。對於這個例子,最小節點覆蓋集合可以只包含一個節點(0或1),所以輸出為1。
再舉一個例子,假設輸入為:
1
2
3
4
5
6
7
8
9
10
|
9
0 1 0 0 0 1 0 0 0
1 0 0 1 0 0 0 1 0
0 0 0 0 1 0 0 0 0
0 1 0 0 0 1 1 0 1
0 0 1 0 0 1 0 0 0
1 0 0 1 1 0 0 0 0
0 0 0 1 0 0 0 0 1
0 1 0 0 0 0 0 0 1
0 0 0 1 0 0 1 1 0
|
對應的最小節點覆蓋集合需要包含3個節點,所以輸出為3。
答題思路
這個題目是要求設計一個演算法程式,能夠從輸入的圖形資料中找出最小節點覆蓋集合的大小,並對於每組輸入資料輸出結果。這是一個經典的組合優化問題,解決方式涉及搜索、貪婪等技術。
參考答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
int minCoveredNodes(vector<vector<int>> &matrix, int n) {
function<vector<vector<int>>(int, int)> getCombination = [](int n, int k) -> vector<vector<int>> {
vector<vector<int>> result;
vector<int> combination;
function<void(int)> recurCombin = [&](int idx) -> void {
if(combination.size() == k) { result.push_back(combination); return; }
for(int i{idx}; i < n; ++i) {
combination.push_back(i);
recurCombin(i + 1);
combination.pop_back();
}
};
recurCombin(0);
return result;
};
function<void(vector<int>&, vector<int>&)> addVec = [](vector<int>& a, vector<int>& b) -> void {
for(int i{0}; i < a.size(); i++) a[i] += b[i];
};
for(int i{1}; i <= n; ++i) {
for(auto &com : getCombination(n, i)) {
vector<int> covered(n, 0);
for(int j{0}; j < i; ++covered[j++]) addVec(covered, matrix[com[j]]);
if(all_of(covered.begin(), covered.end(), [](int n) { return n > 0; })) return i;
}
}
return n;
}
int main() {
int n;
while(cin >> n && n > 0) {
vector<vector<int>> matrix(n, vector<int>(n, 0));
for(int i{0}; i < n; i++) for(int j{0}; j < n; j++) cin >> matrix[i][j];
cout << minCoveredNodes(matrix, n) << endl;
}
return 0;
}
|