定義一個圖的變換:對於一個有向圖\(G=(V, E)\),創建一個新的有向圖:spa
\(V'=\{v_e|e \in E\}\),\(E'=\{(v_b, v_e)|b=(u,v), e=(v,w)\}\),\(G'=(V', E')\)。code
也就是說每一個邊變成一個點,若是邊b的終點和邊e的起點相同則b到e連一條邊。ip
如今給定\(G'\),問是否存在\(G\)。\(G'\)的點數不超過\(300\)。it
若是\(G'\)中有\((u,w), (v,w)\)兩條邊,那麼說明\(G\)中\(u,v\)的終點相同;那麼\(G'\)中\(u,v\)連到的點應該是同樣的。io
也就是說,若是我在\(G'\)中令\(S_i\)表示\(i\)連到的點集,那麼\(S_i=S_j\)和\(S_i\cap S_j\)必有一成立。class
反之,若是上述條件成立,我能夠把全部點按照\(S\)劃分,便可獲得\(G\)中每一個點的出邊集合;而後容易找出\(G\)中每一個點的入邊集合,易證這個\(G\)是合法的。集合
因而bitset求出\(S\)以後枚舉\(i,j\)判斷便可。di
#include <bitset> #include <cstdio> const int N = 305; std::bitset<N> out[N], zero; int main() { int T; scanf("%d", &T); while (T--) { int n, m; scanf("%d%d", &n, &m); zero.reset(); for (int i = 0; i < n; ++i) out[i].reset(); for (int x, y; m; --m) { scanf("%d%d", &x, &y); out[x].set(y); } bool ok = true; for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) ok = ok && ((out[i] & out[j]) == zero || out[i] == out[j]); puts(ok ? "Yes" : "No"); } return 0; }