Problem:
D: DAG トリオ / DAG Trio
この問題は G: DAG Trio (Hard) と制約のみが異なる同じ設定の問題です。
プロローグ
弟は最近「だぐとりお」が欲しいとしきりに呟いています。
心配になった兄が調べたところ、弟のクラスでは $k$-DAG (有向グラフであって、ある $k$ 個の辺を削除すると、辺の向きを無視したときの連結成分数を $k$ にでき、かつそれら全てが DAG である) が流行っており、
3-DAG を特に DAG トリオと呼ぶことを突き止めました。
弟に尊敬されたい兄は、与えられたグラフが DAG トリオかどうかを判別するプログラムを作成することにしました。
問題文
$N$ 頂点 $M$ 辺の有向グラフが与えられます。
各頂点には $1$ から $N$ まで番号が振られています。
各有向辺には $1$ から $M$ まで番号が振られています。
有向辺 $i$ は頂点 $a_i$ から $b_i$ に向かいます。
グラフは連結かつ単純です (辺の向きを無視すると、任意の 2 点間に道があり自己ループと多重辺がありません)。
与えられたグラフが DAG トリオならば ”YES”、そうでないなら ”NO” を出力してください。
入力
$N \ M$
$a_1 \ b_1$
$a_2 \ b_2$
$\vdots$
$a_M \ b_M$
制約
$3 \le N \le 500$
$\max(3, N−1) \le M \le 1000$
$1 \le a_i, b_i \le N$
グラフは辺の向きを無視したときに連結である。
各 $i$ に対して$a_i \neq b_i$
異なる $i, j$ に対して $\{a_i, b_i\} \neq \{a_j, b_j\}$
出力
”YES”　または ”NO” を $1$ 行で出力してください。
サンプル
サンプル入力1
3 3
1 2
2 3
3 1
サンプル出力1
YES
サンプル入力2
6 7
1 2
2 3
4 3
4 5
5 6
6 4
3 6
サンプル出力2
YES
サンプル入力3
7 10
4 2
4 7
4 6
2 7
2 5
2 1
5 6
1 3
6 3
4 3
サンプル出力3
NO
サンプル入力4
4 4
1 2
3 2
4 3
2 4
サンプル出力4
YES
サンプル入力5
8 9
5 1
3 8
1 2
4 8
4 7
7 5
6 5
3 2
4 2
サンプル出力5
YES

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#define int long long
#define N 1000
#define V_MAX 1000
using namespace std;
const int INF = 1LL<<55;
const int mod = (1e9)+7;
const double EPS = 1e-8;
const double PI = 6.0 * asin(0.5);
template<class T> T Max(T &a,T b){return a=max(a,b);}
template<class T> T Min(T &a,T b){return a=min(a,b);}
 
 
class TSort{
public:
  int V;
  vector<set<int> > in,out;
  vector<int> sorted;
  TSort(){V = -1,sorted.push_back(-1);}
  TSort(int V){
    in.resize(V);
    out.resize(V);
    sorted.push_back(-1);
    this->V = V;
  }
   
  void add_edge(int from,int to){
    assert(from < V && to < V);
    assert(out[from].count(to) == 0);
    assert(in[to].count(from) == 0);
    out[from].insert(to);
    in[to].insert(from);
  }
 
  void erase_edge(int from,int to){
    out[from].erase(to);
    in[to].erase(from);
  }
 
  void sort(){
    assert(sorted.size() && sorted[0]==-1 && "sort method is already invoked");
    sorted.clear();
    queue<int> Q;
    for(int i=0;i<V;i++)if(in[i].empty()) Q.push(i);
 
    while(!Q.empty()){
      int v = Q.front();Q.pop();
      sorted.push_back(v);
      for(int nx:out[v]){
        if(in[nx].size() == 1) Q.push(nx);
        in[nx].erase(v);
      }     
    }
     
    for(int i=0;i<V;i++) if(!in[i].empty()) sorted.clear(); // exist loop
  }
};
 

class Bridges{
public:
  typedef pair<int,int> P;
  int V;                  //テ」ツδ偲」ツδシテ」ツδ嘉ヲツ閉ー
  vector <int> G[V_MAX];  //テ」ツつーテ」ツδゥテ」ツδ陛」ツ?ョテゥツ堋」テヲツ篠・テ」ツδェテ」ツつケテ」ツδ暗」ツつ津ィツ。ツィテァツ渉セ
  set <P> bridges; // テヲツゥツ?
  int ord[V_MAX];         //ティツ。ツ古」ツ?催」ツ?凝」ツ?妥ゥツ??」ツつ津」ツ?づ」ツつ湘」ツつ嘉」ツ?凖」ツ??
  int low[V_MAX];         //
 
  Bridges(){V = -1;}
  Bridges(int V){this->V = V;}
   
  void add_edge(int a,int b){
    G[a].push_back(b);
    G[b].push_back(a);
  }
 
  void erase_edge(int a,int b){
    for(int i=0;i<(int)G[a].size();i++) if(G[a][i] == b) {G[a].erase(G[a].begin()+i);break;}
    for(int i=0;i<(int)G[b].size();i++) if(G[b][i] == a) {G[b].erase(G[b].begin()+i);break;}
  }
 
  void dfs(int u, int p, int &c){
    ord[u] = low[u] = c++;
    
    for(int v:G[u]){
      if(v == p)continue;
      if(ord[v] == -1){
        dfs(v,u,c);
        low[u] = min(low[u],low[v]);
      }
      else low[u] = min(low[u], ord[v]);
      if(ord[u] < low[v]) bridges.insert(P(min(u,v),max(u,v)));
    }
  }
  
  void bridge(){
    assert(V >= 0 && "Set number of node V");
    bridges.clear();
    int c = 0;
    memset(ord,-1,sizeof(ord));
    memset(low,0,sizeof(low));
    for(int i=0;i<V;i++) if(ord[i]==-1) dfs(i,-1,c);
  }
   
  bool isBridge(int u,int v){return bridges.count(P(u,v)) || bridges.count(P(v,u));}
};
 
set<int> G[N];
 
signed main(){
  int n,m;
  cin>>n>>m;
  TSort T(n);
  Bridges B(n);
  for(int i=0;i<m;i++){
    int a,b;
    cin>>a>>b;a--,b--;
    T.add_edge(a,b);
    B.add_edge(a,b);
    assert(G[b].count(a)== 0);
    G[a].insert(b);
  }
   
  int ans = 0;
  TSort origin = T;
  for(int from=0;from<n;from++)
    for(int to:G[from]){
      T = origin;
      B.bridge();
      if(B.isBridge(from,to)) continue;
      T.erase_edge(from,to);
      B.erase_edge(from,to);
      
      T.sort();
      B.bridge();
      
      if(T.sorted.size() && (int)B.bridges.size()>=2)ans = 1;
      
      T.add_edge(from,to);
      B.add_edge(from,to);
    }
  cout<<(ans?"YES":"NO")<<endl;
     
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3588
final_rank: 9

code_snippet: #include <bits/stdc++.h>
#define int long long
#define N 1000
#define V_MAX 1000
using namespace std;
const int INF = 1LL<<55;
const int mod = (1e9)+7;
const double EPS = 1e-8;
const double PI = 6.0 * asin(0.5);
template<class T> T Max(T &a,T b){return a=max(a,b);}
template<class T> T Min(T &a,T b){return a=min(a,b);}
 
 
class TSort{
public:
  int V;
  vector<set<int> > in,out;
  vector<int> sorted;
  TSort(){V = -1,sorted.push_back(-1);}
  TSort(int V){
    in.resize(V);
    out.resize(V);
    sorted.push_back(-1);
    this->V = V;
  }
   
  void add_edge(int from,int to){
    assert(from < V && to < V);
    assert(out[from].count(to) == 0);
    assert(in[to].count(from) == 0);
    out[from].insert(to);
    in[to].insert(from);
  }
 
  void erase_edge(int from,int to){
    out[from].erase(to);
    in[to].erase(from);
  }
 
  void sort(){
    assert(sorted.size() && sorted[0]==-1 && "sort method is already invoked");
    sorted.clear();
    queue<int> Q;
    for(int i=0;i<V;i++)if(in[i].empty()) Q.push(i);
 
    while(!Q.empty()){
      int v = Q.front();Q.pop();
      sorted.push_back(v);
      for(int nx:out[v]){
        if(in[nx].size() == 1) Q.push(nx);
        in[nx].erase(v);
      }     
    }
     
    for(int i=0;i<V;i++) if(!in[i].empty()) sorted.clear(); // exist loop
  }
};
 

class Bridges{
public:
  typedef pair<int,int> P;
  int V;                  //???????????°
  vector <int> G[V_MAX];  //??°???????????£??\??????????????¨???
  set <P> bridges; // ???
  int ord[V_MAX];         //?????????????????????????????????
  int low[V_MAX];         //
 
  Bridges(){V = -1;}
  Bridges(int V){this->V = V;}
   
  void add_edge(int a,int b){
    G[a].push_back(b);
    G[b].push_back(a);
  }
 
  void erase_edge(int a,int b){
    for(int i=0;i<(int)G[a].size();i++) if(G[a][i] == b) {G[a].erase(G[a].begin()+i);break;}
    for(int i=0;i<(int)G[b].size();i++) if(G[b][i] == a) {G[b].erase(G[b].begin()+i);break;}
  }
 
  void dfs(int u, int p, int &c){
    ord[u] = low[u] = c++;
    
    for(int v:G[u]){
      if(v == p)continue;
      if(ord[v] == -1){
        dfs(v,u,c);
        low[u] = min(low[u],low[v]);
      }
      else low[u] = min(low[u], ord[v]);
      if(ord[u] < low[v]) bridges.insert(P(min(u,v),max(u,v)));
    }
  }
  
  void bridge(){
    assert(V >= 0 && "Set number of node V");
    bridges.clear();
    int c = 0;
    memset(ord,-1,sizeof(ord));
    memset(low,0,sizeof(low));
    for(int i=0;i<V;i++) if(ord[i]==-1) dfs(i,-1,c);
  }
   
  bool isBridge(int u,int v){return bridges.count(P(u,v)) || bridges.count(P(v,u));}
};
 
set<int> G[N];
 
signed main(){
  int n,m;
  cin>>n>>m;
  TSort T(n);
  Bridges B(n);
  for(int i=0;i<m;i++){
    int a,b;
    cin>>a>>b;a--,b--;
    T.add_edge(a,b);
    B.add_edge(a,b);
    assert(G[b].count(a)== 0);
    G[a].insert(b);
  }
   
  int ans = 0;
  TSort origin = T;
  for(int from=0;from<n;from++)
    for(int to:G[from]){
      T = origin;
      B.bridge();
      if(B.isBridge(from,to)) continue;
      T.erase_edge(from,to);
      B.erase_edge(from,to);
      
      T.sort();
      B.bridge();
      
      if(T.sorted.size() && (int)B.bridges.size()>=2)ans = 1;
      
      T.add_edge(from,to);
      B.add_edge(from,to);
    }
  cout<<(ans?"YES":"NO")<<endl;
     
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3584
final_rank: 8

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define MAX_N 500
#define MAX_M 30000
struct edge{ int from,to,id; };

int N,M;
int a[MAX_M],b[MAX_M];
bool flg[MAX_M];

vector<edge> G[MAX_N];

bool visited[MAX_N];
int depth[MAX_N];
int cnt[MAX_N];
int par[MAX_N];


vector<edge> bridges;


vector<edge> edge_;

void dfs(int pos,int prev){
  visited[pos]=true;
  for(int i=0;i<(int)G[pos].size();i++){
    int to=G[pos][i].to;
    if(to==prev)continue;
    if(!visited[to]){
      depth[to]=depth[pos]+1;
      par[to]=pos;
      dfs(to,pos);
      cnt[pos]+=cnt[to];
      if(cnt[to]==0)bridges.push_back(G[pos][i]);
    }else if(depth[to]<depth[pos]){
      cnt[pos]++;
      cnt[to]--;
      edge_.push_back(G[pos][i]);
    }
  }
}

int countB(int id){
  bridges.clear();
  edge_.clear();
  
  memset(visited,false,sizeof(visited));
  memset(depth,0,sizeof(depth));
  memset(cnt,0,sizeof(cnt));
  memset(par,-1,sizeof(par));
  
  for(int i=0;i<N;i++)G[i].clear();
  for(int i=0;i<M;i++){
    if(i==id)continue;
    G[ a[i] ].push_back( (edge){ a[i],b[i],i } );
    G[ b[i] ].push_back( (edge){ b[i],a[i],i } );
  }
  for(int i=0;i<N;i++){
    if(visited[i])continue;
    dfs(i,-1);
  }
  return bridges.size();
}

bool isDag(int id){
  queue<int> Q;  
  vector<int> C(N,0);
  int cc=0;
  
  for(int i=0;i<N;i++)G[i].clear();
  for(int i=0;i<M;i++){
    if(i==id)continue;
    G[ a[i] ].push_back( (edge){a[i],b[i],i} );
    C[ b[i] ]++;
  }
  for(int i=0;i<N;i++)if(C[i]==0)Q.push(i);

  while(!Q.empty()){
    int pos=Q.front();Q.pop();
    cc++;
    for(int i=0;i<(int)G[pos].size();i++){
      int to=G[pos][i].to;
      C[to]--;
      if(C[to]==0)Q.push(to);
    }
  }
  return (cc==N);
}

void visit(int v){
  if(visited[v])return;
  visited[v]=true;
  for(int i=0;i<(int)G[v].size();i++){
    visit(G[v][i].to);
  }
}

int calcDec(int id){
  for(int i=0;i<N;i++)G[i].clear();
  for(int i=0;i<M;i++){
    if(i==id)continue;
    G[ a[i] ].push_back( (edge){a[i],b[i],i} );
    G[ b[i] ].push_back( (edge){b[i],a[i],i} );
  }
  int res=0;
  memset(visited,false,sizeof(visited));
  for(int i=0;i<N;i++){
    if(!visited[i]){
      res++;
      visit(i);
    }
  }
  return res;
}

map<int,int> mm;
bool check(int id){
  if(mm.count(id))return false;
  mm[id]=true;
  
  if(countB(id) + calcDec(id)>=3&&isDag(id))return true;
  else return false;
}

vector<edge> loope;
bool rec(int pos,int si){
  if(visited[pos])return (pos==si);
  visited[pos]=true;
  for(int i=0;i<(int)G[pos].size();i++){
    edge e=G[pos][i];
    if( rec(e.to,si) ){
      loope.push_back(e);
      return true;
    }
  }
  return false;
}

bool solve2(){
  for(int i=0;i<N;i++)G[i].clear();
  for(int i=0;i<M;i++)G[ a[i] ].push_back( (edge){a[i],b[i],i} );
  
  for(int i=0;i<N;i++){
    memset(visited,false,sizeof(visited));
    loope.clear();
    if( rec(i,i) )break;
  }
  
  for(int i=0;i<(int)loope.size();i++)
    if(check( loope[i].id ))return true;

  return false;
}

bool solve(){
  int B=countB(-1);
  if(B==M)return false;

  for(int i=0;i<M;i++){
    if(check(i)){
      //      cout<<"i="<<i<<" a[i]="<<a[i]<<" b[i]="<<b[i]<<endl;
      return true;
    }
  }
  
  if( !isDag(-1) )return solve2();

  int maxm=0;

  B=countB(-1);
  for(int i=0;i<(int)edge_.size();i++){
    edge e=edge_[i];
    int a=e.from;
    int cc=0;
    while(1){
      if(a==e.to)break;
      if(cnt[a]==1)cc++;
      a=par[a];
      //      cout<<"a="<<a<<endl;
      //      cout<<"par[a]="<<par[a]<<endl;
      //      cout<<e.from<<' '<<e.to<<endl;
    }
    maxm=max(maxm,cc);
  }
  return (B+maxm>=2);
}

int main(){
  cin>>N>>M;
  for(int i=0;i<M;i++){
    cin>>a[i]>>b[i];
    a[i]--;
    b[i]--;
  }
  cout<< ( solve() ? "YES" : "NO" ) <<endl;
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3260
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <stack>
#include <map>

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define all(a)  (a).begin(),(a).end()
#define vi vector<int>
#define pb push_back

int unused_from, unused_to;


#define MAX_V 100000
vector<int> G[MAX_V];
vector<int> Grev[MAX_V];
bool used[MAX_V]={};
int ord[MAX_V],lowlink[MAX_V];
int k=0;

void dfs(int v,int prev){   //make ord and lowlink
    used[v] = true;
    ord[v]=lowlink[v]=k;
    k++;
    
    rep(i,Grev[v].size()){
        int to = Grev[v][i];
        if((v==unused_from&&to==unused_to)||(v==unused_to&&to==unused_from))continue;
        if(!used[to]){
            dfs(to,v);
            lowlink[v] = min(lowlink[v],lowlink[to]);
        }
        else if(used[to]&&to!=prev){    //use back edge
            lowlink[v] = min(lowlink[v],ord[to]);
        }
    }
}

vector<pii> enumerateBridge(int e,vector<pii> edges){   //????????????
    vector<pii> ret;
    
    rep(i,e){
        int a = edges[i].first, b = edges[i].second;
        if((a==unused_from&&b==unused_to)||(a==unused_to&&b==unused_from))continue;
        if(ord[a]>ord[b])swap(a,b);
        if(ord[a]<lowlink[b])ret.pb(pii(edges[i].first,edges[i].second));
    }
    return ret;
}



bool hasLoop(int v){
    vector<int> in_deg(v,0);
    rep(i,MAX_V){
        rep(j,G[i].size()){
            int from = i, to = G[i][j];
            if(from==unused_from&&to==unused_to)continue;
            in_deg[to]++;
        }
    }
    
    stack<int> st;
    vector<int> list;
    
    rep(i,v)if(in_deg[i]==0)st.push(i);
    
    while(st.size()){
        int q = st.top();
        st.pop();
        list.pb(q);
        
        rep(i,G[q].size()){
            int to = G[q][i];
            if(q==unused_from&&to==unused_to)continue;
            in_deg[to]--;
            if(in_deg[to]==0)st.push(to);
        }
    }
    
    if(list.size()!=v)return true;
    return false;
    
}


int main(){
    int v,e;
    cin>>v>>e;
    vector<pii> edges;
    
    rep(i,e){
        int a,b;
        cin>>a>>b;
        a--,b--;
        edges.pb(pii(a,b));
        G[a].pb(b);
        Grev[a].pb(b),Grev[b].pb(a);
    }
    
    
    dfs(0,-1);
    vector<pii> bridge_list = enumerateBridge(e,edges);
    map<pii,bool> mp;
    rep(i,bridge_list.size())mp[bridge_list[i]]=true;
    
    
    rep(i,MAX_V){
        rep(j,G[i].size()){
            unused_from = i;
            unused_to = G[i][j];
            
            rep(i,MAX_V)used[i]=false;
            k=0;
            dfs(0,-1);
            vector<pii> brg = enumerateBridge(e,edges);
            
            if( not mp[pii(unused_from,unused_to)] && brg.size()>=2 && not hasLoop(v)){
                //                cout<<unused_from+1<<" "<<unused_to+1<<endl;  //1????????????????????????????????????
                cout<<"YES"<<endl;
                return 0;
            }
        }
    }
    cout<<"NO"<<endl;
}
accuracy: 1
time_ms: 100
memory_kb: 8060
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define MAX_N 500
#define MAX_M 30000
struct edge{ int from,to,id; };
int N,M;
int a[MAX_M],b[MAX_M];
vector<edge> G[MAX_N];

bool visited[MAX_N];
int depth[MAX_N];
int cnt[MAX_N];
vector<edge> bridges;

void dfs(int pos,int prev){
  visited[pos]=true;
  for(int i=0;i<(int)G[pos].size();i++){
    int to=G[pos][i].to;
    if(to==prev)continue;
    if(!visited[to]){
      depth[to]=depth[pos]+1;
      dfs(to,pos);
      cnt[pos]+=cnt[to];
      if(cnt[to]==0)bridges.push_back(G[pos][i]);
    }else if(depth[to]<depth[pos]){
      cnt[pos]++;
      cnt[to]--;
    }
  }
}

int countB(int id){
  bridges.clear();
  memset(visited,false,sizeof(visited));
  memset(depth,0,sizeof(depth));
  memset(cnt,0,sizeof(cnt));
  for(int i=0;i<N;i++)G[i].clear();
  for(int i=0;i<M;i++){
    if(i==id)continue;
    G[ a[i] ].push_back( (edge){ a[i],b[i],i } );
    G[ b[i] ].push_back( (edge){ b[i],a[i],i } );
  }
  for(int i=0;i<N;i++){
    if(visited[i])continue;
    dfs(i,-1);
  }
  return bridges.size();
}

bool check(int id){
  int B=countB(id);

  memset(visited,false,sizeof(visited));
  int U=0;
  for(int i=0;i<N;i++)
    if(!visited[i])U++,dfs(i,-1);
  
  if(B+U<3)return false;
  
  queue<int> Q;
  vector<int> C(N,0);
  for(int i=0;i<M;i++)
    if(id!=i)C[ b[i] ]++;
  for(int i=0;i<N;i++)
    if(C[i]==0)Q.push(i);
  int cc=0;
  while(!Q.empty()){
    int pos=Q.front();Q.pop();
    cc++;
    for(int i=0;i<(int)G[pos].size();i++){
      int to=G[pos][i].to;
      C[to]--;
      if(C[to]==0)Q.push(to);
    }
  }
  if(cc==N)return true;
  else return false;
}

vector<edge> loope;
bool rec(int pos,int si,int pre=-1){
  if(visited[pos])return (pos==si);
  visited[pos]=true;
  for(int i=0;i<(int)G[pos].size();i++){
    edge e=G[pos][i];
    if(e.id==pre)continue;
    
    if( rec(e.to,si,e.id) ){
      loope.push_back(e);
      return true;
    }
  }
  return false;
}

bool solve2(){

  for(int i=0;i<M;i++){
    if(check(i))return true;
  }
  
  for(int i=0;i<N;i++){
    memset(visited,false,sizeof(visited));
    memset(depth,0,sizeof(depth));
    loope.clear();
    if( rec(i,i) ){
      break;
    }
  }
  for(int i=0;i<(int)loope.size();i++){
    if(check( loope[i].id ))return true;
  }
  return false;
}

bool solve(){
  if(countB(-1)==M)return false;
  
  for(int i=0;i<N;i++)G[i].clear();
  for(int i=0;i<M;i++)G[ a[i] ].push_back( (edge){a[i],b[i],i} );
  if(solve2())return true;
  
  for(int i=0;i<N;i++)G[i].clear();
  for(int i=0;i<M;i++)G[ a[i] ].push_back( (edge){a[i],b[i],i} );
  for(int i=0;i<M;i++)G[ b[i] ].push_back( (edge){b[i],a[i],i} );
  if(solve2())return true;  
  return false;
}

int main(){
  cin>>N>>M;
  for(int i=0;i<M;i++){
    cin>>a[i]>>b[i];
    a[i]--;
    b[i]--;
  }
  cout<< ( solve() ? "YES" : "NO" ) <<endl;
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3248
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define int long long   // <-----!!!!!!!!!!!!!!!!!!!

#define rep(i,n) for (int i=0;i<(n);i++)
#define rep2(i,a,b) for (int i=(a);i<(b);i++)
#define rrep(i,n) for (int i=(n)-1;i>=0;i--)
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define printV(v) for(auto&& x : v){cout << x << " ";} cout << endl
#define printVV(vv) for(auto&& v : vv){for(auto&& x : v){cout << x << " ";}cout << endl;}
#define printP(p) cout << p.first << " " << p.second << endl
#define printVP(vp) for(auto&& p : vp) printP(p);

typedef long long ll;
typedef pair<int, int> Pii;
typedef tuple<int, int, int> TUPLE;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<Pii> vp;
const int inf = 1e9;
const int mod = 1e9 + 7;

typedef vector<vector<int>> Graph;
typedef pair<int, int> Edge; // (a < b: undirected)

class BICC {
private:
    const int n;

public:
    Graph G;
    vi depth;
    vi par;
    map<Edge, int> imosEdge;
    map<Edge, int> EdgeType;
    enum {UNUSED, USED_DFS, BRIDGE};
    vector<Edge> bridges;

	vi cmp;
	int num_cc;
	vi size_of_vertex;
	Graph G_cc;
public:
    BICC(int _n) : n(_n), G(_n), depth(_n, -1), par(_n, -1), cmp(_n, -1), num_cc(0) {}
    Edge getEdge(int a, int b) {
        if (a > b) swap(a, b);
        return Edge(a, b);
    }
    void updateEdgeType(int a, int b, int type) {
        if (a < 0 || b < 0) return;
        EdgeType[getEdge(a, b)] = type;
    }
    void addEdge(int a, int b) {
        G[a].emplace_back(b);
        G[b].emplace_back(a);
        updateEdgeType(a, b, UNUSED);
    }
    void dfsTreeConstruct(int v, int pre) {
        if (depth[v] != -1) return;
        depth[v] = (pre == -1 ? 0 : depth[pre] + 1);
        par[v] = pre;
        updateEdgeType(pre, v, USED_DFS);
        for (auto&& nxt : G[v]) {
            if (nxt != pre) dfsTreeConstruct(nxt, v);
        }
    }
    void updateImos(int a, int b) {
        if (depth[a] < depth[b]) swap(a, b);

        if (par[a] != -1) {
            imosEdge[getEdge(a, par[a])]++;
        }
        if (par[b] != -1) {
            imosEdge[getEdge(b, par[b])]--;
        }
    }
    int imosFinal(int v, int pre) {
        int t = 0;
        for (auto&& nxt : G[v]) {
            if (nxt != pre && EdgeType[getEdge(nxt, v)] == USED_DFS) {
                t += imosFinal(nxt, v);
            }
        }
        if (pre != -1) imosEdge[getEdge(v, pre)] += t;
        return pre == -1 ? 0 : imosEdge[getEdge(v, pre)];
    }
    int extractCC(int v, int color) {
    	if (cmp[v] != -1) return 0;
    	cmp[v] = color;
    	int t = 1;
    	for (auto&& nxt : G[v]) {
    		if (EdgeType[getEdge(v, nxt)] != BRIDGE) {
    			t += extractCC(nxt, color);
    		}
    	}
    	return t;
    }
    void bicc() {
        dfsTreeConstruct(0, -1);
        for (auto&& p : EdgeType) {
            Edge e;
            int type;
            tie(e, type) = p;
            if (type == UNUSED) {
                updateImos(e.first, e.second);
            }
        }
        imosFinal(0, -1);
        for (auto&& p : EdgeType) {
            Edge e;
            int type;
            tie(e, type) = p;
            if (type == USED_DFS) {
                if (imosEdge[e] == 0) {
                    EdgeType[e] = BRIDGE;
                    bridges.emplace_back(e);
                }
            }
        }

		rep(i, n) {
			int size_cc = extractCC(i, num_cc);
			if (size_cc > 0) {
				size_of_vertex.emplace_back(size_cc);
				num_cc++;
			}
		}

	 	vector<set<int>> G_cc_st(num_cc);
		for (auto&& p : EdgeType) {
            Edge e;
            int type;
            tie(e, type) = p;
            if (type == BRIDGE) {
				G_cc_st[cmp[e.first]].insert(cmp[e.second]);
				G_cc_st[cmp[e.second]].insert(cmp[e.first]);
            }
        }

		rep(i, num_cc) {
			G_cc.emplace_back(vector<int>(all(G_cc_st[i])));
		}
    }
    vector<Edge> getBridges() {
        return bridges;
    }
};


// false: "contains cycle"
bool dfs(int now, int start, const Graph &G, vector<bool> &visited) {
    visited[now] = true;
    for (auto nxt : G[now]) {
        if (nxt == start) return false;
        if (!visited[nxt] && !dfs(nxt, start, G, visited)) return false;
    }
    return true;
}

bool isDAG(const Graph &G) {
    int n = G.size();
    rep(i, n) {
        vector<bool> visited(n);
        if (!dfs(i, i, G, visited)) return false;
    }
    return true;
}

void dfs2(int v, int pre, const Graph& G, vector<bool>& visited) {
    if (visited[v]) return;
    visited[v] = true;
    for (auto nxt : G[v]) {
        if (v == pre) continue;
        dfs2(nxt, v, G, visited);
    }
}

bool isConnected(const Graph& G) {
    int n = G.size();
    vector<bool> visited(n);
    dfs2(0, -1, G, visited);
    rep(i, n) {
        if (!visited[i]) return false;
    }
    return true;
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

    int N, M;
    cin >> N >> M;
    vector<pair<int, int>> edges;
    rep(i, M) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        edges.emplace_back(a, b);
    }

    rep(i, M) {
        BICC bicc(N);
        Graph G_dir(N);
        rep(j, M) {
            if (j == i) continue;
            bicc.addEdge(edges[j].first, edges[j].second);
            G_dir[edges[j].first].emplace_back(edges[j].second);
        }

        // ??????????????????????????¨????????°??????????????£??????????????????????????????
        if (!isConnected(bicc.G)) {
            continue;
        }

        bicc.bicc();

        if (bicc.num_cc >= 3 && isDAG(G_dir)) {
            cout << "YES" << endl;
            return 0;
        }
    }

    cout << "NO" << endl;
}
accuracy: 1
time_ms: 680
memory_kb: 3404
final_rank: 12

code_snippet: #define _USE_MATH_DEFINES
#include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <complex>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <limits>
#include <climits>
#include <cfloat>
#include <functional>
using namespace std;

bool topologicalSort(const vector<vector<int> >& edges, vector<int>& node)
{
    int n = edges.size();
    node.resize(n);

    vector<int> restEdges(n, 0);
    for(int i=0; i<n; ++i){
        for(unsigned j=0; j<edges[i].size(); ++j){
            ++ restEdges[edges[i][j]];
        }
    }

    int restNodes = n;
    queue<int> q;
    for(int i=0; i<n; ++i){
        if(restEdges[i] == 0){
            node[n-restNodes] = i;
            q.push(i);
            -- restNodes;
        }
    }

    while(restNodes > 0){
        if(q.empty()){
            node.clear();
            return false;
        }
        int i = q.front();
        q.pop();

        for(unsigned j=0; j<edges[i].size(); ++j){
            int k = edges[i][j];
            -- restEdges[k];
            if(restEdges[k] == 0){
                node[n-restNodes] = k;
                q.push(k);
                -- restNodes;
            }
        }
    }

    return true;
}

bool isBridge(const vector<vector<int> >& edges, int a, int b)
{
    int n = edges.size();
    queue<int> q;
    vector<bool> check(n, false);
    q.push(a);
    check[a] = true;
    while(!q.empty()){
        int x = q.front();
        q.pop();
        for(int y : edges[x]){
            if(!(x == a && y == b) && !check[y]){
                q.push(y);
                check[y] = true;
            }
        }
    }
    return !check[b];
}

void bridgeDecomposition(const vector<vector<int> >& edges, vector<int>& indexConvert,
                         vector<vector<int> >& nodesOut, vector<vector<int> >& edgesOut)
{
    const int n = edges.size();
    vector<int> num(n, -1), low(n, -1);
    vector<bool> isStk(n, false);
    stack<int> stk;
    int cnt = -1;
    nodesOut.clear();

    for(int i=0; i<n; ++i){
        stack<tuple<int, int, unsigned> > arg;
        arg.push(make_tuple(i, -1, 0));

        while(!arg.empty()){
            int v      = get<0>(arg.top());
            int prev   = get<1>(arg.top());
            unsigned j = get<2>(arg.top());
            arg.pop();

            if(j == 0){
                if(num[v] != -1)
                    continue;
                num[v] = low[v] = ++ cnt;
                stk.push(v);
                isStk[v] = true;
            }
            else{
                int w = edges[v][j-1];
                if(w != prev && isStk[w])
                    low[v] = min(low[v], low[w]);
            }

            if(j < edges[v].size()){
                arg.push(make_tuple(v, prev, j + 1));
                int w = edges[v][j];
                if(w != prev)
                    arg.push(make_tuple(w, v, 0));
            }
            else if(low[v] == num[v]){
                nodesOut.push_back(vector<int>());
                for(;;){
                    int w = stk.top();
                    stk.pop();
                    isStk[w] = false;
                    nodesOut.back().push_back(w);
                    if(v == w)
                        break;
                }
            }
        }
    }

    const int m = nodesOut.size();
    indexConvert.resize(n);
    for(int i=0; i<m; ++i){
        for(unsigned j=0; j<nodesOut[i].size(); ++j)
            indexConvert[nodesOut[i][j]] = i;
    }
    edgesOut.assign(m, vector<int>());
    vector<set<int> > used(m);
    for(int i=0; i<n; ++i){
        for(unsigned j=0; j<edges[i].size(); ++j){
            int v = indexConvert[i];
            int w = indexConvert[edges[i][j]];
            if(v != w && used[v].find(w) == used[v].end()){
                edgesOut[v].push_back(w);
                used[v].insert(w);
            }
        }
    }
}

int main()
{
    int n, m;
    cin >> n >> m;
    vector<vector<int> > edges(n), directedEdges(n);
    for(int i=0; i<m; ++i){
        int a, b;
        cin >> a >> b;
        -- a;
        -- b;
        edges[a].push_back(b);
        edges[b].push_back(a);
        directedEdges[a].push_back(b);
    }

    for(int a=0; a<n; ++a){
        for(unsigned i=0; i<directedEdges[a].size(); ++i){
            int b = directedEdges[a][i];
            if(isBridge(edges, a, b))
                continue;

            vector<vector<int> > directEdges2 = directedEdges;
            directEdges2[a].erase(find(directEdges2[a].begin(), directEdges2[a].end(), b));
            vector<int> tmp;
            if(!topologicalSort(directEdges2, tmp))
                continue;

            vector<vector<int> > edges2 = edges;
            edges2[a].erase(find(edges2[a].begin(), edges2[a].end(), b));
            edges2[b].erase(find(edges2[b].begin(), edges2[b].end(), a));
            vector<int> tmp1;
            vector<vector<int> > nodes, tmp2;
            bridgeDecomposition(edges2, tmp1, nodes, tmp2);

            if(nodes.size() >= 3){
                cout << "YES" << endl;
                return 0;
            }
        }
    }

    cout << "NO" << endl;
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3208
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;

const int MAX = 555;
int N ,M, V;
vector<int> G[MAX];
vector<int> rG[MAX];
bool used[MAX];
int cmp[MAX];
vector<int> vs;

void add_edge(int from,int to){
  G[from].push_back(to);
  rG[to].push_back(from);
}
  
void dfs(int v){
  used[v] = true;
  for(int i = 0 ; i < (int)G[v].size() ; i++){
    if(!used[G[v][i]]) dfs(G[v][i]);
  }
  vs.push_back(v);
}
  
void rdfs(int v,int k){
  used[v] = true;
  cmp[v] = k;
  for(int i = 0 ; i < (int)rG[v].size() ; i++){
    if(!used[rG[v][i]]) rdfs(rG[v][i],k);
  }
}
  
int scc(){ //?????£?????????????§£????????????
  memset(used, 0, sizeof(used));
  vs.clear();
  for(int v = 0 ; v < V ; v++){
    if(!used[v]) dfs(v);
  }   
  memset(used, 0, sizeof(used));
  int k = 0;
  for(int i = vs.size() - 1 ; i >= 0 ; i--){
    if(!used[vs[i]]) rdfs(vs[i],k++);
  }
  return k;
}

int ord[MAX], low[MAX];
struct edgeB{
  int u,v;
};
 
void dfs(int u, int pre, int &c, vector<int> G[], vector<edgeB> &B){
  ord[u] = low[u] = c++;
  for(int i=0;i<(int)G[u].size();i++){
    int v = G[u][i];
    if(v != pre){
      if(ord[v] == -1){
        dfs(v,u,c,G,B);
        low[u] = min(low[u],low[v]);
      }
      else{
        low[u] = min(low[u],ord[v]);
      }
      if(ord[u] < low[v]) B.push_back((edgeB){u,v});
    }
  }
}
 
void bridge(int n, vector<int> G[], vector<edgeB> &B){
  B.clear();
  int c = 0;
  fill(ord,ord+n,-1);
  for(int i=0;i<n;i++) if(ord[i]==-1) dfs(i,-1,c,G,B);
}


int A[1111],B[1111];

void make_graph(int x){
  for(int i=0;i<N;i++) G[i].clear();
  for(int i=0;i<N;i++) rG[i].clear();
  for(int i=0;i<M;i++){
    if( i == x ) continue;
    add_edge( A[i], B[i] );
  }
}

void make_graph2(int x){
  for(int i=0;i<N;i++) G[i].clear();
  for(int i=0;i<M;i++){
    if( i == x ) continue;
    G[A[i]].push_back( B[i] );
    G[B[i]].push_back( A[i] );
  }
}

int main(){
  cin >> N >> M;  
  V = N;
  for(int i=0;i<M;i++){
    cin >> A[i] >> B[i]; --A[i]; --B[i];
  }
  if( N == 3 ){
    cout << "YES" << endl; return 0;
  } else if( M == N-1 ){
    cout << "NO" << endl; return 0;
  }
  
  for(int i=0;i<M;i++){
    make_graph(i);
    int n = scc();
    if( n == N ){
      make_graph2(i);
      vector<edgeB> E;
      bridge( N, G, E );
      if( E.size() >= 2 ) {
	cout << "YES" << endl; return 0;
      }
    }
  }
  cout << "NO" << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 1284
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> pii;
typedef long long ll;
typedef vector<int> vi;

#define pb push_back
#define eb emplace_back
#define mp make_pair
#define fi first
#define se second
#define rep(i,n) rep2(i,0,n)
#define rep2(i,m,n) for(int i=m;i<(n);i++)
#define ALL(c) (c).begin(),(c).end()

class unionfind {
	vector<int> par, rank;

public:
	void init(int n) {
		par.resize(n);
		rank.resize(n);

		for (int i = 0; i < n; i++) {
			par[i] = i;
			rank[i] = 0;
		}
	}

	int find(int x) {
		if (par[x] == x) return x;
		else return par[x] = find(par[x]);
	}

	void unite(int x, int y) {
		x = find(x);
		y = find(y);
		if (x == y) return ;

		if (rank[x] < rank[y]) par[x] = y;
		else {
			par[y] = x;
			if (rank[x] == rank[y]) ++rank[x];
		}
	}

	bool same(int x, int y) { return (find(x) == find(y)); }
} uf;

#define MAX_V 510

int V;
vector<int> G[MAX_V], rG[MAX_V];
vector<int> vs; 

bool vis[MAX_V];
int cmp[MAX_V]; 

void add_edge(int from, int to)
{
	G[from].pb(to);
	rG[to].pb(from);
}

void dfs(int v)
{
	vis[v] = true;

	for (int to : G[v]) {
		if (!vis[to]) dfs(to);
	}

	vs.push_back(v);
}

void rdfs(int v, int k)
{
	vis[v] = true;
	cmp[v] = k;

	for (int to : rG[v]) {
		if (!vis[to]) rdfs(to, k);
	}
}

int scc()
{
	memset(vis, 0, sizeof(vis));
	vs.clear();

	rep(v, V) if (!vis[v]) dfs(v);

	memset(vis, 0, sizeof(vis));

	int k = 0;
	reverse(ALL(vs));

	for (int v : vs) {
		if (!vis[v]) rdfs(v, k++);
	}

	return k;
}

class LOWLINK {
public:
	int V;
	vector<int> G[510];
	vector<pair<int, int> > bridge;
	int ord[510], low[510];
	bool vis[510];
	bool not1[510];

	void init(int _V)
	{
		V = _V;
		memset(vis, 0, sizeof(vis));
		memset(not1, 0, sizeof(not1));
		rep(i, V) G[i].clear();
		bridge.clear();
	}

	void calc()
	{
		int k = 0;
		rep(i, V) if (!vis[i]) DFS(i, -1, k);

	}

	void add_edge(int a, int b)
	{
		G[a].pb(b); G[b].pb(a);
	}

	void DFS(int v, int p, int &k)
	{
		vis[v] = true;

		ord[v] = k++;
		low[v] = ord[v];

		bool isArticulation = false;
		int ct = 0;

		for (int i = 0; i < G[v].size(); i++) {
			if (!vis[G[v][i]]) {
				ct++;
				DFS(G[v][i], v, k);
				low[v] = min(low[v], low[G[v][i]]);
				if (ord[v] < low[G[v][i]]) {
					bridge.push_back(make_pair(min(v, G[v][i]), max(v, G[v][i])));
				} else {
					not1[v] = not1[G[v][i]] = 1;
				}
			}
			else if (G[v][i] != p) {
				low[v] = min(low[v], ord[G[v][i]]);
			}
		}
	}
} T;

int N, M;
int A[50010], B[50010];
int in[510];

int main() {
	scanf("%d %d", &N, &M);

	V = N;

	rep(i, M) {
		scanf("%d%d", &A[i], &B[i]);
		--A[i]; --B[i];
		//add_edge(A[i], B[i]);
	}

	rep(i, M) {
		T.init(N);
		rep(j, N) {
			G[j].clear();
			rG[j].clear();
		}

		rep(j, M) if (j != i) {
			add_edge(A[j], B[j]);
			T.add_edge(A[j],B[j]);
			T.add_edge(B[j],A[j]);
		}

		int now = scc();
		uf.init(N);

		bool ok = 1;

		rep(j, N) {
			for (int to : G[j]) {
				if (cmp[j] == cmp[to]) {
					ok = 0;
				}
				uf.unite(j, to);
			}
		}

		rep(j, N) {
			if (!uf.same(0,j)) ok=0;
		}
		T.calc();

		if (ok && T.bridge.size() >= 2) {
			puts("YES");
			return 0;
		}
	}
	puts("NO");
	return 0;

	int num = scc();

	if (num == N) {
		puts("CASE1");
		T.init(N);

		rep(i, M) {
			T.add_edge(A[i], B[i]);
			T.add_edge(B[i], A[i]);
		}
		T.calc();

		cout<<T.bridge.size()<<endl;

		bool size_3 = 0;
		rep(i, N) if (T.not1[i]) size_3 = 1;
		if (size_3 && T.bridge.size() >= 2) {
			puts("YES");
		} else {
			puts("NO");
		}
	} else {
		puts("CASE2");
		memset(in, -1, sizeof(in));

		vi cand;
		int id = -1;
		rep(i, N) cout << cmp[i] << endl;
		rep(i, M) {
			if (cmp[A[i]] == cmp[B[i]]) {
				if (in[B[i]] != -1 || (id != -1 && cmp[A[i]] != id)) {
					puts("NO");
					return 0;
				}

				id = cmp[A[i]];
				in[B[i]] = A[i];
				cand.pb(A[i]);
			}
		}
		cout<<cand.size()<<endl;

		if (num - 1 + (int)cand.size() != N) {
			puts("NO");
			return 0;
		}

		puts("DEB");
		for (int v : cand) {
			T.init(N);
			rep(i, M) {
				if (!(A[i] == in[v] && B[i] == v)) {
					T.add_edge(A[i], B[i]);
					T.add_edge(B[i], A[i]);
				}
			}
			T.calc();
			if ((int)T.bridge.size() >= 2) {
				puts("YES");
				return 0;
			}
		}

		puts("NO");
		return 0;
	}


	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3336
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;

#define int long long
typedef vector<int>vint;
typedef pair<int,int>pint;
typedef vector<pint>vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define pb push_back
#define fi first
#define se second
template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}

namespace SCC{
    void visit(const vector<vector<int>>&G,vector<int>&vs,vector<int>&used,int v){
        used[v]=true;
        for(auto u:G[v]){
            if(!used[u])visit(G,vs,used,u);
        }
        vs.push_back(v);
    }

    void visit2(const vector<vector<int>>&T,vector<int>&used,vector<int>&comp,vector<int>&vec,int k,int v){
        comp[v]=k;
        used[v]=true;
        vec.push_back(v);

        for(auto u:T[v]){
            if(!used[u])visit2(T,used,comp,vec,k,u);
        }
    }

    //G:?????£?????????????§£???????????°??????
    //H:?????£??????????????°??????1???????????????????´?????????°??????
    //comp:G????????????????????????H?????????????±????????????????
    void decompose(const vector<vector<int>>&G,vector<vector<int>>&H,vector<int>&comp){
        vector<vector<int>>T(G.size());
        for(int i=0;i<G.size();i++){
            for(auto v:G[i]){
                T[v].push_back(i);
            }
        }
        comp.resize(G.size());

        vector<int>vs(G.size());
        vector<int>used(G.size());
        for(int i=0;i<G.size();i++){
            if(!used[i])visit(G,vs,used,i);
        }
        reverse(vs.begin(),vs.end());
        fill(used.begin(),used.end(),0);

        int K=0;
        vector<vector<int>>S;
        for(auto v:vs){
            if(!used[v]){
                S.push_back(vector<int>());
                visit2(T,used,comp,S.back(),K++,v);
            }
        }

        H.resize(K);
        fill(used.begin(),used.end(),0);
        for(int i=0;i<K;i++){
            for(auto v:S[i]){
                for(auto u:G[v]){
                    if(used[comp[u]]||comp[v]==comp[u])continue;
                    used[comp[u]]=true;
                    H[comp[v]].push_back(comp[u]);
                }
            }
            for(auto v:H[i])used[v]=false;
        }

    }
}

struct UF{
    vector<int>par,sz;
    void init(int n){
        par.resize(n);
        sz.resize(n);
        for(int i=0;i<n;i++){
            par[i]=i;
            sz[i]=1;
        }
    }
    int find(int x){
        return x==par[x]?x:par[x]=find(par[x]);
    }
    void unite(int x,int y){
        x=find(x);y=find(y);
        if(x==y)return;
        sz[x]+=sz[y];
        par[y]=x;
    }
    bool same(int x,int y){
        return find(x)==find(y);
    }
    int size(int x){
        return sz[find(x)];
    }
};

vector<vint>G;
vector<pair<int, int> > bridge;
int ord[1000], low[1000];
bool vis[1000];

void dfs(int v, int p, int &k)
{
	vis[v] = true;

	ord[v] = k++;
	low[v] = ord[v];

	for (int i = 0; i < G[v].size(); i++){
		if (!vis[G[v][i]]){
			dfs(G[v][i], v, k);
			low[v] = min(low[v], low[G[v][i]]);
			if (ord[v] < low[G[v][i]]) bridge.push_back(make_pair(min(v, G[v][i]), max(v, G[v][i])));
		}
		else if (G[v][i] != p){
			low[v] = min(low[v], ord[G[v][i]]);
		}
	}
}

int A[100000],B[100000];

signed main(){
    int N,M;
    cin>>N>>M;
    rep(i,M)cin>>A[i]>>B[i],A[i]--,B[i]--;

    bool flag=false;
    int deg[1000]={};
    {
        vector<vint>G(N),H;
        rep(i,M)G[A[i]].pb(B[i]);
        vint comp;
        SCC::decompose(G,H,comp);
        rep(i,M){
            if(comp[A[i]]==comp[B[i]])deg[B[i]]++;
        }
        if(H.size()==N)flag=true;
    }

    if(!flag){
        rep(i,M){
            if(deg[B[i]]!=1)continue;
            UF uf;
            uf.init(N);
            rep(j,M)if(i!=j)uf.unite(A[j],B[j]);
            bool ok=true;
            rep(j,N)if(uf.find(j)!=uf.find(0))ok=false;
            if(!ok)continue;
            G=vector<vint>(N);
            rep(j,M)if(i!=j)G[A[j]].pb(B[j]);
            vector<vint>H;vint comp;
            SCC::decompose(G,H,comp);
            if(H.size()!=N)continue;
            G=vector<vint>(N);
            rep(j,M)if(i!=j)G[A[j]].pb(B[j]),G[B[j]].pb(A[j]);
            memset(vis,0,sizeof(vis));
            int K=0;
            bridge.clear();
            dfs(0,-1,K);
            if(bridge.size()>=2){
                cout<<"YES"<<endl;
                return 0;
            }
        }
        cout<<"NO"<<endl;
        return 0;
    }
    else{
        rep(i,M){
            UF uf;
            uf.init(N);
            rep(j,M)if(i!=j)uf.unite(A[j],B[j]);
            bool ok=true;
            rep(j,N)if(uf.find(j)!=uf.find(0))ok=false;
            if(!ok)continue;
            G=vector<vint>(N);
            rep(j,M)if(i!=j)G[A[j]].pb(B[j]);
            vector<vint>H;vint comp;
            SCC::decompose(G,H,comp);
            if(H.size()!=N)continue;
            G=vector<vint>(N);
            rep(j,M)if(i!=j)G[A[j]].pb(B[j]),G[B[j]].pb(A[j]);
            memset(vis,0,sizeof(vis));
            int K=0;
            bridge.clear();
            dfs(0,-1,K);
            if(bridge.size()>=2){
                cout<<"YES"<<endl;
                return 0;
            }
        }
        cout<<"NO"<<endl;
        return 0;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3272
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define for_(i,a,b) for(int i=(a);i<(b);++i)
#define for_rev(i,a,b) for(int i=(a);i>=(b);--i)
#define allof(a) (a).begin(),(a).end()
#define minit(a,b) memset(a,b,sizeof(a))
#define size_of(a) int((a).size())
#define cauto const auto

typedef pair< int, int > pii;
template< typename T > using Vec = vector< T >;

class StronglyConnectedComponentDecomposition {
public:
	struct Result {
		Vec< int > topol;
		Vec< Vec< int > > dag;
	};
	
private:
	int N;
	const Vec< Vec< int > >& adj;
	Vec< Vec< int > > rev_adj;
	
	Vec< int > rev_order;
	Vec< bool > used;	
	Vec< int > topol;
	
	void dfs(int v) {
		used[v] = true;
		for (int u : adj[v]) if (!used[u]) dfs(u);
		rev_order.push_back(v);
	}
	
	void revDfs(int v, int k) {
		used[v] = true;
		topol[v] = k;
		for (int u : rev_adj[v]) if (!used[u]) revDfs(u, k);
	}
	
public:
	StronglyConnectedComponentDecomposition(const Vec< Vec< int > >& _adj_) : N(_adj_.size()), adj(_adj_) {
		rev_adj.assign(N, Vec< int >());
		for_(v,0,N) for (int u : adj[v]) rev_adj[u].push_back(v);
	}
	
	Result decomposition() {
		used.assign(N, false);
		rev_order.clear();
		topol.assign(N, -1);
		
		for_(v,0,N) if (!used[v]) dfs(v);
		
		fill(allof(used), false);
		
		int k = 0, m = rev_order.size();
		
		for_rev(i,m-1,0) {
			int v = rev_order[i];
			if (!used[v]) revDfs(v, k++);
		}
		
		Vec< Vec< int > > dag(k);
		
		for_(v,0,N) {
			int tv = topol[v];
			
			for (int u : adj[v]) {
				int tu = topol[u];
				if (tv != tu) dag[tv].push_back(tu);
			}
		}
		
		for_(i,0,k) {
			sort(allof(dag[i]));
			dag[i].erase(unique(allof(dag[i])), dag[i].end());
		}
		
		return Result{ topol, dag };
	}
};

class FindBridge {
private:
	int V;
	Vec< set< int > > adj;
	
	Vec< int > low, pre;
	Vec< bool > vis;
	
	int dfs(int v, int& count, int p, Vec< pii >& br) {
		pre[v] = count++;
		low[v] = pre[v];
		vis[v] = true;
		
		for (int u : adj[v]) {
			if (pre[u] == -1) {
				low[v] = min(low[v], dfs(u, count, v, br));
				if (low[u] == pre[u]) br.push_back(pii(v, u));
			} else {
				if (u != p) low[v] = min(low[v], low[u]);
			}
		}
		
		return low[v];
	}
	
public:
	FindBridge(int V__) : V(V__), adj(V__, set< int >()) {}
	
	void addEdge(int u, int v) {
		adj[u].insert(v);
		adj[v].insert(u);
	}
	
	Vec< pii > get() {
		Vec< pii > br;
		low.assign(V, -1);
		pre.assign(V, -1);
		vis.assign(V, false);
		int count = 0;
		for_(v,0,V) if (!vis[v]) dfs(0, count, -1, br);
		return br;
	}
	
	int count() {
		Vec< pii > br;
		low.assign(V, -1);
		pre.assign(V, -1);
		vis.assign(V, false);
		int count = 0;
		for_(v,0,V) if (!vis[v]) dfs(0, count, -1, br);
		return br.size();
	}
};

int N, M, a[1010], b[1010];
bool isbr[1010];
Vec< Vec< int > > adj;

typedef StronglyConnectedComponentDecomposition SCC;

int doSCC() {	
	SCC::Result scc = SCC(adj).decomposition();
	Vec< int > vcnt(N, 0);
	for_(v,0,N) vcnt[scc.topol[v]]++;
	int szov2 = 0;
	for_(i,0,N) if (vcnt[i] >= 2) szov2++;
	return szov2;
}

void findBr() {
	FindBridge fb(N);
	for_(i,0,M) fb.addEdge(a[i], b[i]);
	Vec< pii > vp = fb.get();
	
	for (pii p : vp) {
		for_(i,0,M) {
			if (p.first == a[i] && p.second == b[i]) isbr[i] = true;
			if (p.first == b[i] && p.second == a[i]) isbr[i] = true;
		}
	}
}

void solve() {
	findBr();
	
	for_(ig,0,M) {
		if (isbr[ig]) continue;
		adj.assign(N, Vec< int >());
		
		for_(i,0,M) {
			if (i == ig) continue;
			adj[a[i]].push_back(b[i]);
		}
		
		if (doSCC() == 0) {
			FindBridge fb(N);

			for_(i,0,M) {
				if (i == ig) continue;
				fb.addEdge(a[i], b[i]);
			}
			
			if (fb.count() >= 2) {
				puts("YES");
				exit(0);
			}
		}
	}
	
	puts("NO");
}

int main() {
	cin >> N >> M;
	for_(i,0,M) {
		cin >> a[i] >> b[i];
		--a[i]; --b[i];
	}
	solve();
}
accuracy: 1
time_ms: 60
memory_kb: 3300
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;

#define int long long
typedef vector<int>vint;
typedef pair<int,int>pint;
typedef vector<pint>vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define pb push_back
#define fi first
#define se second
template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}

namespace SCC{
    void visit(const vector<vector<int>>&G,vector<int>&vs,vector<int>&used,int v){
        used[v]=true;
        for(auto u:G[v]){
            if(!used[u])visit(G,vs,used,u);
        }
        vs.push_back(v);
    }

    void visit2(const vector<vector<int>>&T,vector<int>&used,vector<int>&comp,vector<int>&vec,int k,int v){
        comp[v]=k;
        used[v]=true;
        vec.push_back(v);

        for(auto u:T[v]){
            if(!used[u])visit2(T,used,comp,vec,k,u);
        }
    }

    //G:?????£?????????????§£???????????°??????
    //H:?????£??????????????°??????1???????????????????´?????????°??????
    //comp:G????????????????????????H?????????????±????????????????
    void decompose(const vector<vector<int>>&G,vector<vector<int>>&H,vector<int>&comp){
        vector<vector<int>>T(G.size());
        for(int i=0;i<G.size();i++){
            for(auto v:G[i]){
                T[v].push_back(i);
            }
        }
        comp.resize(G.size());

        vector<int>vs(G.size());
        vector<int>used(G.size());
        for(int i=0;i<G.size();i++){
            if(!used[i])visit(G,vs,used,i);
        }
        reverse(vs.begin(),vs.end());
        fill(used.begin(),used.end(),0);

        int K=0;
        vector<vector<int>>S;
        for(auto v:vs){
            if(!used[v]){
                S.push_back(vector<int>());
                visit2(T,used,comp,S.back(),K++,v);
            }
        }

        H.resize(K);
        fill(used.begin(),used.end(),0);
        for(int i=0;i<K;i++){
            for(auto v:S[i]){
                for(auto u:G[v]){
                    if(used[comp[u]]||comp[v]==comp[u])continue;
                    used[comp[u]]=true;
                    H[comp[v]].push_back(comp[u]);
                }
            }
            for(auto v:H[i])used[v]=false;
        }

    }
}

struct UF{
    vector<int>par,sz;
    void init(int n){
        par.resize(n);
        sz.resize(n);
        for(int i=0;i<n;i++){
            par[i]=i;
            sz[i]=1;
        }
    }
    int find(int x){
        return x==par[x]?x:par[x]=find(par[x]);
    }
    void unite(int x,int y){
        x=find(x);y=find(y);
        if(x==y)return;
        sz[x]+=sz[y];
        par[y]=x;
    }
    bool same(int x,int y){
        return find(x)==find(y);
    }
    int size(int x){
        return sz[find(x)];
    }
};

vector<vint>G;
vector<pair<int, int> > bridge;
int ord[1000], low[1000];
bool vis[1000];

void dfs(int v, int p, int &k)
{
	vis[v] = true;

	ord[v] = k++;
	low[v] = ord[v];

	for (int i = 0; i < G[v].size(); i++){
		if (!vis[G[v][i]]){
			dfs(G[v][i], v, k);
			low[v] = min(low[v], low[G[v][i]]);
			if (ord[v] < low[G[v][i]]) bridge.push_back(make_pair(min(v, G[v][i]), max(v, G[v][i])));
		}
		else if (G[v][i] != p){
			low[v] = min(low[v], ord[G[v][i]]);
		}
	}
}
signed main(){
    int N,M;
    int A[1000],B[1000];
    cin>>N>>M;
    rep(i,M)cin>>A[i]>>B[i],A[i]--,B[i]--;

    rep(i,M){
        UF uf;
        uf.init(N);
        rep(j,M)if(i!=j)uf.unite(A[j],B[j]);
        bool ok=true;
        rep(j,N)if(uf.find(j)!=uf.find(0))ok=false;
        if(!ok)continue;
        G=vector<vint>(N);
        rep(j,M)if(i!=j)G[A[j]].pb(B[j]);
        vector<vint>H;vint comp;
        SCC::decompose(G,H,comp);
        if(H.size()!=N)continue;
        G=vector<vint>(N);
        rep(j,M)if(i!=j)G[A[j]].pb(B[j]),G[B[j]].pb(A[j]);
        memset(vis,0,sizeof(vis));
        int K=0;
        bridge.clear();
        dfs(0,-1,K);
        if(bridge.size()>=2){
            cout<<"YES"<<endl;
            return 0;
        }
    }
    cout<<"NO"<<endl;
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3268
final_rank: 10