传送门:​​点击打开链接​

题意:每两个点之间必有且仅有一条有向边,问是否存在一个3元环。

思路:这题与普通的求环有2个不一样的地方,一个是每两个点必有一条边,一个是只是求3元环而已。。然而我们可以证明,如果每两个点之间必有一条边存在环,那么必然会存在3元环。假设某一个n元环上存在a->b->c->d这样的4个,如果d就是a,那么(a,b,c)就直接构成了3元环之间满足题意。如果d不是a,那么就必有a->c,那么又形成了a->c->d,也就是说,n元环退化到n-1元环。以此可以继续递推下去,最后可以证明出,只要存在环,那么必有3元环~

不得不吐槽一句,刚开始一直用getchar一直超时,一改成scanf用%s就过了- -

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck printf("fuck")
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;

const int MX = 2000 + 5;

int IN[MX];
char G[MX][MX];

int main() {
int T, n, ansk = 0; //FIN;
scanf("%d", &T);
while(T--) {
memset(IN, 0, sizeof(IN));
scanf("%d", &n);

for(int i = 1; i <= n; i++) {
scanf("%s", G[i] + 1);
for(int j = 1; j <= n; j++) {
if(G[i][j] == '1') IN[j]++;
}
}

queue<int>Q;
for(int i = 1; i <= n; i++) {
if(!IN[i]) Q.push(i);
}

int ans = 0;
while(!Q.empty()) {
int u = Q.front();
Q.pop();
ans++;

for(int v = 1; v <= n; v++) {
if(G[u][v]) {
IN[v]--;
if(!IN[v]) Q.push(v);
}
}
}

printf("Case #%d: %s\n", ++ansk, ans == n ? "No" : "Yes");
}
return 0;
}