定义一个图的变换:对于一个有向图\(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; }