# 題目: UVa 11659 - Informants
# 題目說明
題目給 n 個線人,並給 a 條規則,求最大可信賴的線人數
線人編號由 1 ~ n
若 1 可信賴,則 1 說的規則為真
若 1 不可信賴,則 1 說的規則可能為真或假
INPUT:
每筆測資先輸入兩個整數 n 、 a , n 代表線人數、 a 代表規則數
接下來有 a 行,每行輸入兩個整數 x 、 y
- 若
y > 0,代表線人x信賴線人y - 若
y < 0,代表線人x不信賴線人y
OUTPUT:
輸出最大可信賴的線人數
# 解題方法
使用 correct 與 wrong 分別儲存信賴與不信賴,儲存分法為 2進位
若線人 1 信賴線人 3 與 4 ,則表示成 correct[1] = 1100
若線人 2 不信任線人 1 、 3 與 4 ,則表示成 wrong[2] = 1101
遍歷所有可能的線人組合
若 n = 4 ,則遍歷 0000 、 0001 、 ... 、 1111 所有可能
分別判斷各個線人是否存在這次的線人組合中
j 代表第 j 位線人, j 屬於 1 ~ n
若存在則進一步判斷規則是否有矛盾
線人 j 不信賴的線人是否存在於這次線人組合
線人 j 信賴的線人是否不存在於這次線人組合
若以上有至少一項為 是 ,則此線人組合矛盾
當此組合中的線人全部判斷完,且規則都沒有矛盾,則可計算這次可信賴的線人數
# 參考程式碼
#include <iostream> | |
#include <vector> | |
using namespace std; | |
static auto fast_io = [] | |
{ | |
ios::sync_with_stdio(false); | |
cout.tie(nullptr); | |
cin.tie(nullptr); | |
return 0; | |
}(); | |
int main() | |
{ | |
int n, a, x, y; | |
while (cin >> n >> a, n + a) | |
{ | |
// init | |
vector<int> correct(n + 1, 0); | |
vector<int> wrong(n + 1, 0); | |
int max_num = (1 << n); | |
int ret = 0; | |
// input | |
for (int i = 0; i < a; ++i) | |
{ | |
cin >> x >> y; | |
if (y > 0) correct[x] |= (1 << (y - 1)); // if 1 trust 3 and 4, correct[1] = 1100 | |
else wrong[x] |= (1 << (-y - 1)); | |
} | |
for (int i = 0; i < max_num; ++i) // all possible combination | |
{ | |
bool feasible = true; | |
for (int j = 1; j <= n; ++j) // each person | |
{ | |
int p = 1 << (j - 1); | |
if ((i & p) == 0) continue; // j doesn't exist in i | |
if ((i & wrong[j]) != 0 || (i & correct[j]) != correct[j]) // is there a contradiction | |
{ | |
feasible = false; | |
break; | |
} | |
} | |
if (feasible) | |
{ | |
int cnt = 0, cpy = i; | |
while (cpy) cnt += cpy & 1, cpy >>= 1; // count the number of '1' in i (bitwise) | |
ret = max(ret, cnt); | |
} | |
} | |
cout << ret << "\n"; | |
} | |
} |
# 參考資料
https://theriseofdavid.github.io/2021/04/23/UVa/UVa11659/