going from u to v or from v to u
输入:
第一行包含单个整数t,即测试用例的数量。
每个样例的第一行包含两个整数n,m(0 <n <1001,m <6000),表示洞穴中的房间和走廊的数量(走廊是单向的)。接下来的m行每行包含两个整数u和v,表示有一个连接房间u和房间v的走廊。
输出:
输出应包含t行。如果洞穴中存在可以互相到达的房间,则输出“Yes”,否则输出“No”。
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <stack>
#include <vector>
using namespace std;
int t = 0;
int visited[1002]; //是否被访问过
int curcolor;
int dfn[1002];
int low[1002];
int color[1002]; //用于染色
int sumcolor[1002]; //相同颜色块的数量
int ntime;
stack<int> s;
void tarjan(int u, vector<int>* v)
{
visited[u] = 1;
s.push(u);
dfn[u] = ++ntime;
low[u] = ntime;
for (int i = 0; i < v[u].size(); i++)
{
int q = v[u][i];
if (visited[q] == 0)
{
tarjan(q, v);
low[u] = min(low[u], low[q]);
}
else
low[u] = min(low[u], dfn[q]);
}
if (dfn[u] == low[u])
{
int v = s.top();
s.pop();
while (v != u) //染色
{
color[v] = curcolor;
v = s.top();
s.pop();
}
color[u] = curcolor;
curcolor++;
}
}
int main()
{
cin >> t;
int m, n;
while (t--)
{
memset(color, 0, sizeof(color));
memset(visited, 0, sizeof(visited));
curcolor = 1;
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(sumcolor, 0, sizeof(sumcolor));
ntime = 0;
vector<int> v[6002];
cin >> n >> m;
for (int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
v[a].push_back(b);
}
for (int i = 1; i <= n; i++)
{
if (visited[i] == 0)
tarjan(i, v);
}
int flag = 0;
for (int i = 1; i <= n; i++)
{
sumcolor[color[i]]++;
if (sumcolor[color[i]] >= 2) //相同颜色块的数量
{
flag = 1;
cout << "Yes" << endl;
break;
}
}
if (flag == 0)
cout << "No" << endl;
}
return 0;
}