---
tags: Graph
---
# a136: 元件測試排程問題
- 以 bitmask 紀錄每個節點前、後要有哪些節點。
- 如果節點 A 同時出現在節點 B 的前與後表示發生衝突了。
``` cpp=
#include <iostream>
#include <vector>
#include <set>
using namespace std;
const int R_NO_ANSWER = 0,
R_FOUND_ORDER = 1,
R_CONFLICT = 2;
struct Node {
int pre = 0, // 前面有哪些節點(bit mask)
post = 0; // 後面有哪些節點(bit mask)
vector<int> child; // 下一個節點清單
};
int n, m;
vector<Node> g;
string order;
// DFS 展開測試順序
bool expand(int index, int me)
{
order[index] = 'A' + me;
if (index == n-1)
return true;
for (auto &c: g[me].child) {
if (expand(index+1, c))
return true;
}
return false;
}
int main()
{
char s, t;
set<int> head; // 可當成起點的節點
int result = R_NO_ANSWER,
cause_pair = 0;
cin >> n >> m;
g.resize(n);
order.assign(n, ' ');
for (int i = 0; i < n; i++)
head.insert(i);
for (int i = 1; i <= m; i++) {
cin >> s >> t;
s -= 'A';
t -= 'A';
g[s].child.push_back(t); // 把 t 加到 s 的後面
g[s].post |= (1 << t) | g[t].post; // s 後續可到的節點為 t 的後續節點加上 t
g[t].pre |= (1 << s) | g[s].pre; // t 的前置節點為 s 的前置節點加上 s
for (int j = 0, mask = 1; j < n; j++, mask <<= 1) {
if (g[s].pre & mask) // 更新 s 前置節點的後續節點
g[j].post |= g[s].post;
if (g[t].post & mask) // 更新 t 後續節點的前置節點
g[j].pre |= g[t].pre;
}
if (g[t].post & g[t].pre) { // 前置與後續有共同的節點 -> loop
result = R_CONFLICT;
cause_pair = i;
break;
} else if (result == R_NO_ANSWER) { // 還沒有答案
head.erase(t); // t 不能當成起點(因為 s 要在 t 前面)
if (head.size() == 1 && expand(0, *head.begin())) { // 僅有一個起點時再展開就好,多個起點無法決定順序
result = R_FOUND_ORDER;
cause_pair = i;
}
}
}
if (result == R_NO_ANSWER)
cout << "No answer\n";
else if (result == R_FOUND_ORDER)
cout << "Determine the testing sequence after getting pair " << cause_pair << " : " << order << '\n';
else
cout << "Order conflict after getting pair " << cause_pair << '\n';
return 0;
}
```