zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Matlab中transpose函数的使用
    Matlab中cell2mat的使用
    Matlab中find函数的使用
    Matlab中数组下标是logical,如何处理?
    Matlab中mat2cell的使用
    判断一棵树是否是另一棵树的子树
    链表中倒数第k个结点
    古德-图灵估计
    好书记录
    编程思路总结——递归
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12245449.html
Copyright © 2011-2022 走看看