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: Accepted)

#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 10005

enum Type{
	NONE,
	START,
	FINISH,
};

struct Heap{
	Heap(){
		left = NULL;
		right = NULL;
		diff = 0;
		cost = 0;
		edge_id = 0;
	}

	Heap(int arg_cost,int arg_edge_id){
		left = NULL;
		right = NULL;
		diff = 0;
		cost = arg_cost;
		edge_id = arg_edge_id;
	}
	Heap *left,*right;
	int diff,cost,edge_id;
};

struct Edge{
	Edge(int arg_from,int arg_to,int arg_cost){
		from = arg_from;
		to = arg_to;
		cost = arg_cost;
	}
	int from,to,cost;
};

int V,E;
int boss[NUM];
int table_index;
int in_num[NUM];
int from_cost[NUM],FROM[NUM];
vector<Edge> edge;
Heap heap_table[1000005];
Heap* HEAP[NUM];
Type type[NUM];


void lazy(Heap* A){

	if(A->left){
		A->left->diff += A->diff;
	}
	if(A->right){
		A->right->diff += A->diff;
	}
	A->cost += A->diff;
	A->diff = 0;
}


Heap* meld(Heap* A,Heap* B){

	if(!A){
		return B;
	}
	if(!B){
		return A;
	}

	if((A->cost+A->diff) > (B->cost+B->diff)){
		swap(A,B);
	}

	lazy(A);

	A->right = meld(A->right,B);
	swap(A->left,A->right);

	return A;
}

Heap* pop(Heap *A){
	lazy(A);
	return meld(A->left,A->right);
}



int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

int is_same(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	if(boss_x == boss_y)return;

	boss[boss_x] = boss_y;
}

void init(){

	for(int i = 0; i < V; i++){
		boss[i] = i;
	}
}

int MCA(int root){

	init();
	table_index = 0;

	for(int i = 0; i < V; i++){
		type[i] = NONE;
		HEAP[i] = NULL;
	}
	type[root] = FINISH;

	for(int i = 0; i < edge.size(); i++){

		heap_table[table_index] = Heap(edge[i].cost,i);
		HEAP[edge[i].to] = meld(HEAP[edge[i].to],&heap_table[table_index++]);
	}

	int ret = 0;

	for(int start = 0; start < V; start++){

		if(type[start] != NONE)continue;

		int current = start;
		vector<int> USED;

		while(type[current] != FINISH){

			type[current] = START;
			USED.push_back(current);

			if(!HEAP[current]){
				return BIG_NUM;
			}

			FROM[current] = get_boss(edge[HEAP[current]->edge_id].from);

			from_cost[current] = HEAP[current]->cost+HEAP[current]->diff;

			HEAP[current] = pop(HEAP[current]);

			if(FROM[current] == current)continue;

			ret += from_cost[current];

			if(type[FROM[current]] == START){

				int tmp = current;
				int debug = 0;

				do{
					if(HEAP[tmp]){
						HEAP[tmp]->diff -= from_cost[tmp];
					}

					if(tmp != current){
						unite(tmp,current);
						HEAP[current] = meld(HEAP[current],HEAP[tmp]);
					}

					tmp = get_boss(FROM[tmp]);

				}while(tmp != current);


			}else{
				current = FROM[current];
			}
		}

		for(int k = 0; k < USED.size(); k++){
			type[USED[k]] = FINISH;
		}
	}
	return ret;
}

int main(){

	scanf("%d %d",&V,&E);

	for(int i = 0; i < V; i++){

		in_num[i] = 0;
	}

	int from,to;

	for(int loop = 0; loop < E; loop++){

		scanf("%d %d",&from,&to);
		in_num[to]++;

		edge.push_back(Edge(from,to,0));
		edge.push_back(Edge(to,from,1));
	}

	vector<int> ANS;
	int min_cost = BIG_NUM,tmp;

	for(int i = 0; i < V; i++){

		if(in_num[i] > 0)continue;

		tmp = MCA(i);

		if(min_cost > tmp){

			min_cost = tmp;
			ANS.clear();
			ANS.push_back(i);

		}else if(min_cost == tmp){

			ANS.push_back(i);
		}
	}

	printf("%lld %d\n",ANS.size(),min_cost);

	printf("%d",ANS[0]);
	for(int i = 1; i < ANS.size(); i++){
		printf(" %d",ANS[i]);
	}
	printf("\n");

	return 0;
}