简单的 dfs,O(n^2)遍历,对每个点 u,都遍历一遍图
判断以 u 为起点的图是否含有 diamond
其实就是判断 u 的子节点 vi, vj 的子图是否经过同一个点
标记一下就行了
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = 1010;
const int MOD = 1e9+7;
const int INF = 0xFFFFFFF;
#define rep(i, x, y) for (int i=x; i<=y; i++)
#define mset(arr) memset(arr, 0, sizeof(arr))
int T, N, M;
vector<int> v[maxn];
bool vis[maxn];
void init() {
for (int i = 0; i <= N; ++i)
v[i].clear();
}
//判断以 u 为起点的子图是否与其他子图有重合
bool dfs(int u) {
//找到了重合点
if (vis[u]) return true;
vis[u] = true;
int to;
for (int i = 0; i < v[u].size(); ++i)
{
to = v[u][i];
if( dfs(to) )
return true;
}
return false;
}
//判断以 u 为根的图是否包含 diamond diagram
bool have(int u) {
int to;
for (int i = 0; i < v[u].size(); ++i)
{
to = v[u][i];
if( dfs(to) )
return true;
}
return false;
}
int main() {
freopen("a.in", "r", stdin);
freopen("b.out", "w", stdout);
cin>>T;
for (int kase = 1; kase <= T; ++kase)
{
cin>>N;
init();
for (int i = 1; i <= N; ++i)
{
cin>>M;
int p;
for (int j = 0; j < M; ++j)
{
cin>>p;
v[i].push_back(p);
}
}
bool yes = 0;
for (int i = 1; i <= N; ++i)
{
memset(vis, 0, sizeof(vis));
if( have(i) ) {
yes = 1;
break;
}
}
printf("Case #%d: ", kase);
printf("%s\n", yes ? "Yes" : "No");
}
return 0;
}