题解
题目的就是问所给的图是不是强连通图,有向图找强连通可以使用tarjan算法求出强连通分量个数,如果为1则输出Yes
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
#define fs first
#define sc second
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 1e4 + 10;
vector<int> e[MAXN];
int dfn[MAXN], low[MAXN], cnt, idx; //节点编号 当前节点为根的子树能到达的最小节点 节点所在强连通分量的最小节点编号 强连通分量数
bool vis[MAXN]; //在栈内的点
int stk[MAXN], tot;
int Tarjan(int x)
{
dfn[x] = low[x] = ++idx;
stk[++tot] = x, vis[x] = 1; //进栈
for (int y : e[x])
if (!dfn[y]) //还未访问
Tarjan(y), low[x] = min(low[x], low[y]); //访问并且取min
else if (vis[y]) //已经访问并且在栈中
low[x] = min(low[x], low[y]); //取min
if (low[x] == dfn[x]) //当前强连通分量的最小节点
{
int y;
cnt++; //强连通分量数量+1
do
{
y = stk[tot--], vis[y] = 0; //出栈
} while (y != x);
}
}
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int n, m;
while (scanf("%d%d", &n, &m), n || m) //不是n && m
{
cnt = idx = tot = 0;
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
for (int i = 1; i <= n; i++)
e[i].clear();
for (int i = 0; i < m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
e[u].push_back(v);
}
for (int i = 1; i <= n; i++)
if (!dfn[i]) //未访问
Tarjan(i);
if (cnt == 1)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}