Problem:
閉路のない連結な有向グラフが与えられる．(有向グラフが連結であるとは，これを無向グラフとした時に連結であるという事である．)

このグラフに対して一つの頂点を選んで首都 s を定めたい．

T(v) = "v から全ての点を到達可能にするために必要な「辺の反転」操作の回数の最小値"とする．

ただし，「辺の反転」とは，頂点 v, u に関して (v, u) に張られていた有向辺を削除して (u, v) に張り直すことである．

頂点 s が首都であるとは任意の頂点 v に対して， T(s) ≤ T(v) が成立することである．

首都であるような頂点をすべて列挙して答えよ．

Input

入力は以下のような形式で M + 1 行で与えられる．

N M
a1 b1
:
aM bM

1 行目には二つの整数 N, M が与えられ，与えられるグラフは N 頂点 M 辺であることを表す．

2 行目から M + 1 行目にはそれぞれ二つの整数 ai, bi が与えられ，ai から bi に有向辺が張られていることを表す．

Constraints

1 ≤ N ≤ 10,000

0 ≤ M ≤ 100,000

0 ≤ ai ≤ N − 1

0 ≤ bi ≤ N − 1

ai ≠ bi

i ≠ j ならば (ai, bi) ≠ (aj, bj)

与えられるグラフは連結で閉路はない．

与えられるグラフに対して，入次数が 0 である頂点の個数は 50 以下である．

Output

以下の形式で2 行で出力せよ．

cnum cost
c1 c2 . . . ccnum

1 行目には二つの整数 cnum, cost を空白区切りで出力せよ．

2 行目には cnum 個の整数 ci を空白区切りで出力せよ．

変数の意味は以下の通りである．

     − cnum : 首都の性質を満たす頂点数

     − cost : 首都となる頂点 v に対する T(v) の値

     − ci : 首都の性質を満たす頂点を番号に関して昇順に並べた時，i 番目の頂点番号

Sample Input 1

3 2
0 1
2 1

Output for the Sample Input 1

2 1
0 2

頂点 0 を首都とするときには辺 (2,1) を反転すれば，(0,1), (1,2) の辺を持つグラフができるので 1 が答え．

T(0) = 1, T(1) = 2, T(2) = 1 である．

Sample Input 2

5 4
0 1
2 1
2 3
4 3

Output for the Sample Input 2

3 2
0 2 4

Sample Input 3

5 5
0 1
1 2
3 2
3 4
4 1

Output for the Sample Input 3

2 1
0 3

Solution in C++ (judge verdict: Time Limit Exceeded)

#include<bits/stdc++.h>
using namespace std;
int INF=1e9;
 
struct UnionFind{
  vector<int> par,rank;
  void init(int n){
    par.clear();
    rank.clear();
    par.resize(n);
    rank.resize(n);
    for(int i=0;i<n;i++){
      par[i]=i;
      rank[i]=1;
    }
  }
   
  int find(int x){
    if(x==par[x])return x;
    return par[x]=find(par[x]);
  }
 
  bool same(int x,int y){
    return ( find(x)==find(y) );
  }
   
  void unite(int x,int y){
    x=find(x);
    y=find(y);
    if(x==y)return;
    if(rank[x]<rank[y])swap(x,y);
    par[y]=x;
    rank[x]+=rank[y];
  }
};
 
struct edge{
  int from,to,cost,id;
  bool operator < (const edge e)const{
    return cost > e.cost;
  }
};
 
typedef priority_queue< edge > prque;
typedef prque* Prque;
 
typedef vector<edge> Node;
typedef vector<Node> Graph;
 
 
Prque Merge(vector< Prque > &Q, vector<edge> &ev,int A,int C){
  if( Q[C]->size() < Q[A]->size() ){
 
    while( !Q[C]->empty() ){
      edge e=Q[C]->top();
      e.cost-=ev[C].cost;
      e.cost+=ev[A].cost;
      Q[A]->push(e);
      Q[C]->pop();
    }
    ev[C].cost=ev[A].cost;
    return Q[A];
  }else{
    while( !Q[A]->empty() ){
      edge e=Q[A]->top();
      e.cost-=ev[A].cost;
      e.cost+=ev[C].cost;
      Q[C]->push(e);
      Q[A]->pop();
    }
    return Q[C];
  }
}
 
int solve(Graph &G,vector<edge> &edges,int root){
 
  int n=G.size(), res=0;
  vector<int> used(n,0);
  vector< edge > ev(n, (edge){0,0,0,-1} );
  vector< prque > pool(n);
  vector< Prque > Q(n);
  for(int i=0;i<n;i++)Q[i]=&pool[i];
   
  UnionFind uf;
  uf.init(n);
   
  for(int i=0;i<(int)edges.size();i++){
    edge e=edges[i];
    Q[ e.to ]->push( e );
  }
   
  used[root]=2;
  for(int Pos=0;Pos<n;Pos++){
    if(used[Pos]==2)continue;
    int pos=Pos;
    vector<int> path;
     
    while( used[pos] != 2 ){
      pos=uf.find(pos);
       
      used[pos]=1;
      path.push_back(pos);
      if( Q[pos]->empty() ){
        return INF;
      }
       
      edge e=Q[pos]->top();
 
       
      Q[pos]->pop();
      e.cost-=ev[pos].cost;
      if( uf.same(e.from,pos) ) continue;
      int tmpcost=ev[pos].cost;

      res+=e.cost;
      e.cost+=tmpcost;
      ev[pos]=e;
      if( used[ uf.find(e.from) ] == 2 )break;
      if( used[ uf.find(e.from) ] == 0 ){
        pos=e.from;
        continue;
      }
      int pre=uf.find(e.from);
      
      while(1){

        
        if(!uf.same(pre,pos)){
          int A=uf.find(pre), B=uf.find(pos);
          uf.unite(A,B);
          int C=uf.find(A);
          Prque tmp=NULL;
          if(B==C)tmp=Merge(Q,ev,A,C);
          else if(A==C)tmp=Merge(Q,ev,B,C);
          else assert(0);
           
          Q[C]=tmp;
        }
        pre=uf.find(ev[pre].from);

        if(pre==pos)break;
      }
    }// while_pos
 
    for(int i=0;i<(int)path.size();i++)used[ path[i] ]=2;
  }// Pos
  return res;
}
 
int main(){
  map<int,bool> mp;
  int V,E;
  vector<edge> edges;
  Graph G;
  cin>>V>>E;
  G.resize(V);
  for(int i=0;i<E;i++){
    int a,b;
    cin>>a>>b;
    mp[b]=true;
    G[a].push_back( (edge){a,b,0,i} );
    edges.push_back( (edge){a,b,0,i} );
     
    G[b].push_back( (edge){b,a,1,i} );
    edges.push_back( (edge){b,a,1,i} );
  }
 
  int mini=1e9;
  vector<int> ans;
  for(int i=0;i<V;i++){
    if(mp[i])continue;
    int val=solve(G,edges,i);
     
    if( mini > val ){
      mini=val;
      ans.clear();
      ans.push_back(i);
    }else if( mini == val ){
      ans.push_back(i);
    }
  }
 
  cout<<ans.size()<<' '<<mini<<endl;
  for(int i=0;i<(int)ans.size();i++){
    if(i)cout<<' ';
    cout<<ans[i];
  }
  cout<<endl;
  return 0;
}