传送门:点击打开链接
题意:每两个点之间必有且仅有一条有向边,问是否存在一个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;
}