题意:
给出n个人的喜欢关系,mp[i][j] == 1表示i喜欢j,规定若a不喜欢b,则b一定喜欢a,问这些关系中是否存在三角恋的关系,即(a->b,b->c,c->a)。
思路:
题目的要求下,显然任意两个人之间一定有一条单向边,那么可以发现如果存在环,一定至少有一个长度为3的环,画一画就能看出来。
所以这道题只需要判断是否存在环即可,可以利用拓扑排序,也可以直接dfs搜环。
代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <queue>
using namespace std;
const int MAXN = 2005;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
int indeg[MAXN], seq[MAXN];
vector <int> G[MAXN];
int topo(int n) {
queue <int> q;
for (int i = 0; i < n; i++) {
if (indeg[i] == 0) q.push(i);
}
int k = 0;
bool res = false;
while (!q.empty()) {
if (q.size() != 1) res = true;
int u = q.front(); q.pop();
seq[k++] = u;
for(int i = 0; i < (int)G[u].size(); i++) {
int v = G[u][i];
indeg[v]--;
if(indeg[v] == 0)
q.push(v);
}
}
if (k < n) return -1; ///存在有向环,总之不能进行拓扑排序
if (res) return 0; ///可以进行拓扑排序,并且只有唯一一种方式,seq数组即是排序完好的序列
return 1; ///可以进行拓扑排序,有多种情况,seq数组是其中一种序列
}
char mp[MAXN][MAXN];
int main() {
int T, cs = 0;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
memset(indeg, 0, sizeof(indeg));
for (int i = 0; i < n; i++) {
scanf("%s", mp[i]);
for (int j = 0; j < n; j++) {
if (mp[i][j] == '1') {
G[i].push_back(j);
indeg[j]++;
}
}
}
printf("Case #%d: ", ++cs);
if (topo(n) == -1) puts("Yes");
else puts("No");
}
return 0;
}