解法:
竞赛图没有自环,没有二元环;若竞赛图存在环,则一定存在三元环。
简单证明:
假设一个竞赛图存在一个 N 元环(大于三元),环上有连续三点 A , B , C ( 存在有向边 AB , BC )
根据竞赛图的定义,一定存在有向边 CA 或 AC 中的一者。
情况 1 :若存在 CA ,则 A , B , C 构成三元环;
情况 2 :若存在 AC ,不考虑 B 点,剩下的点构成一个 (N-1) 元环。显然,如果一直不存在情况 1 的话,最终也会形成一个三元环。
(出处:https://www.luogu.com.cn/blog/sanmukl/solution-cf117c)
故找到环后不断缩减环的长度即可找到三元环。
Code:
1 #include <bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 5 int n; 6 const int maxn=5010; 7 int grid[maxn][maxn]; 8 int checked[maxn]; 9 stack<int> stk; 10 int ring[maxn]; 11 int ridx; 12 int instack[maxn]; 13 14 bool dfs(int u){ 15 16 17 if(checked[u]) return false; 18 19 if(instack[u]){ 20 //printf("%d %d", u,stk.top()); 21 while(stk.top()!=u){ 22 ring[ridx++]=stk.top(); 23 stk.pop(); 24 } 25 ring[ridx]=u; 26 27 return true; 28 } 29 30 stk.push(u); 31 instack[u]=1; 32 for(int i=1;i<=n;++i){ 33 if(grid[u][i]){ 34 if(dfs(i)) return true; 35 } 36 } 37 instack[u]=0; 38 stk.pop(); 39 checked[u]=1; 40 return false; 41 } 42 43 int main(){ 44 scanf("%d", &n); 45 string s; 46 for(int i=1;i<=n;++i){ 47 48 for(int j=1;j<=n;++j){ 49 char c=getchar(); 50 while(c!='0' && c!='1') c=getchar(); 51 grid[i][j]=c-'0'; 52 } 53 } 54 int i; 55 for(i=1;i<=n;++i){ 56 if(dfs(i)) break; 57 } 58 if(i>n){ 59 printf("-1"); 60 return 0; 61 } 62 63 stack<int> tmp; 64 for(int i=0;i<=ridx;++i){ 65 tmp.push(ring[i]); 66 } 67 int t=0; 68 while(!tmp.empty()){ 69 ring[t++]=tmp.top(); 70 tmp.pop(); 71 } 72 73 for(int i=2;i<=ridx;++i){ 74 if(grid[ring[i]][ring[0]]){ 75 printf("%d %d %d", ring[0], ring[i-1], ring[i]); 76 return 0; 77 } 78 } 79 80 return 0; 81 }