板子
单联通图的定义就是题中所说的
由其定义可知,tarjan缩点之后的每个SCC中的任意两个点均可到达
每个SCC之间必然构成一条链
#include <cstdio>
#include <cctype>
#include <queue>
#include <cmath>
#include <cstdlib>
#include <cstring>
using namespace std;
template <typename T> inline void read(T &x) {
int ch = getchar();
bool f = false;
for (x = 0; !isdigit(ch); ch = getchar()) {
if (ch == '-') {
f = true;
}
}
for (; isdigit(ch); ch = getchar()) {
x = x * 10 + ch - '0';
}
if (f) {
x = -x;
}
}
const int MAXN = 20100;
const int MAXE = 200400;
const int INF = 0x3f3f3f3f;
using std::min;
struct Edge {
int to, nxt;
Edge() {}
Edge(int _to, int _nxt) : to(_to), nxt(_nxt) {}
}E[MAXE];
int h[MAXN], ins[MAXN], dfn[MAXN], Clock_t, Stack[MAXN], SCC;
int top, belong[MAXN], in[MAXN], sz[MAXN], cnt, low[MAXN];
int vis[MAXN], n, m;
inline void add_edge(int u, int v) {
E[++cnt] = Edge(v, h[u]), h[u] = cnt;
}
void Tarjan(int x) {
ins[x] = 1;
low[x] = dfn[x] = ++Clock_t;
Stack[++top] = x;
for(int i = h[x]; ~i; i = E[i].nxt) {
int v = E[i].to;
if(!dfn[v]) {
Tarjan(v);
low[x] = min(low[x], low[v]);
}
else if(ins[v]) low[x] = min(low[x], dfn[v]);
}
if(low[x] == dfn[x]) {
SCC++;int v;
do {
v = Stack[top--];
ins[v] = 0;
belong[v] = SCC;
sz[SCC]++;
}while(v != x);
}
return ;
}
int T;
namespace toposort {
Edge E[MAXE];
int h[MAXN], cnt = 0, in[MAXN];
void add_edge(int a, int b) {
E[++cnt] = Edge(b, h[a]), h[a] = cnt;
}
queue<int> q;
int node[MAXN], tot;
void init() {
memset(h, 0, sizeof(h));
cnt = tot = 0;
memset(in, 0, sizeof(in));
}
int solve() {
tot = 0;
for(int i = 1; i <= SCC; i++) {
if(!in[i]) {
q.push(i);
}
}
while(!q.empty()) {
int u = q.front(); q.pop();
if(!q.empty()) {
while(!q.empty()) q.pop();
return 0;
}
tot++;
for(int i = h[u]; i; i = E[i].nxt) {
int v = E[i].to;
in[v]--;
if(!in[v]) q.push(v);
}
}
return tot == SCC;
}
}
signed main() {
read(T);
while(T--) {
memset(h, -1, sizeof(h));
cnt = 0;
memset(ins, 0, sizeof(ins)); memset(in, 0, sizeof(in));
memset(low, 0, sizeof(low)); memset(sz, 0, sizeof(sz));
memset(dfn, 0, sizeof(dfn)); memset(belong, 0, sizeof(belong));
Clock_t = SCC = top = 0;
read(n), read(m);
for(int i = 1; i <= m; i++) {
int a, b; read(a), read(b);
add_edge(a, b);
}
for(int i = 1; i <= n; i++)
if(!dfn[i])
Tarjan(i);
toposort::init();
for(int x = 1; x <= n; x++)
for(int i = h[x]; ~i; i = E[i].nxt) {
int to = E[i].to;
if(belong[x] != belong[to]) {
toposort::add_edge(belong[x], belong[to]);
toposort::in[belong[to]]++;
}
}
if(toposort::solve()) printf("Yes\n");
else printf("No\n");
}
return 0;
}