CF117C Cycle (竞赛图找环)

题目链接

 解法:

竞赛图没有自环,没有二元环;若竞赛图存在环,则一定存在三元环。

简单证明:

假设一个竞赛图存在一个 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 }
原文地址:https://www.cnblogs.com/FEIIEF/p/12245449.html