根据题意,需要满足在一个有向图中满足任意两点之间可以互相到达,也就是说这个图的最大连通子图就是它本身,Tarjan算法找一下强联通分量即可,且强连通分量个数为1。。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO \
ios::sync_with_stdio(false); \
// cin.tie(0); \
// cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e4 + 10;
const int maxm = 1e5 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 11092019;
int dis[8][2] = {0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
struct Edge
{
int before;
int to;
} e[maxm];
int n, m, k, tim, top, dfn[maxn], low[maxn], st[maxn], head[maxn];
bool vis[maxn];
int cnt = 0; // 记录强联通分量个数
void add(int u, int v)
{
e[k].before = head[u];
e[k].to = v;
head[u] = k++;
}
void Tarjan(int u)
{
low[u] = dfn[u] = ++tim;
st[++top] = u;
vis[u] = true;
for (int i = head[u]; i != -1; i = e[i].before)
{
int v = e[i].to;
if (!dfn[v])
{
Tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (vis[v])
{
low[u] = min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u])
{
++cnt;
int t;
while (t = st[top--])
{
vis[t] = false;
if (u == t)
break;
}
}
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
while (scanf("%d %d", &n, &m))
{
if (n == 0 && m == 0)
break;
memset(head, -1, sizeof head);
memset(dfn, 0, sizeof dfn);
k = 0, cnt = 0, tim = 0, top = 0;
int a, b;
for (int i = 0; i < m; i++)
{
scanf("%d %d", &a, &b);
add(a, b);
}
for (int i = 1; i <= n; i++)
if (!dfn[i])
Tarjan(i);
printf(cnt == 1 ? "Yes\n" : "No\n");
}
return 0;
}