#include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld=long double;



vector<int>get_costs(const vector<vector<int>>&edges, const vector<vector<int>>&rev_edges, const int start, vector<int>&ids) {

	priority_queue<pair<int ,int>>que;
	que.push(make_pair(0,start));
	vector<int>memo(edges.size(),1000000);
	memo[start]=0;
	while (!que.empty()) {
		auto atop(que.top());
		que.pop();

		const int now=atop.second;
		const int now_cost=-atop.first;

		for (auto e : edges[now]) {
			const int next_cost=now_cost;
			if (memo[e] > next_cost) {
				memo[e]=next_cost;
				que.push(make_pair(-next_cost,e));
			}
		}
		for (auto e : rev_edges[now]) {
			const int next_cost=now_cost+1;
			if (memo[e] > next_cost) {
				memo[e]=next_cost;
				que.push(make_pair(-next_cost,e));
			}
		}
	}
	vector<int>anss(ids.size());
	for (int i = 0; i < ids.size(); ++i) {
		anss[i]=memo[ids[i]];
	}
	return anss;
}

typedef long long int Weight;

const Weight INF = 2147483647;
const Weight ZERO = 0;
struct Edge {
	int src, dst;
	Weight weight;
	int id;
	Edge(int src_, int dst_, Weight weight_, const int id_) :
		src(src_), dst(dst_), weight(weight_), id(id_) { }
	Edge(int src, int dst, Weight weight) :
		src(src), dst(dst), weight(weight) { }
	Edge() :src(0), dst(0), weight(0) {
	}
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
namespace getcycle {
	vector<Edge>get_cycle(const Graph&g, const int start) {
		vector<Edge>prev_es(g.size());
		for (auto es : g) {
			for (auto e : es) {
				prev_es[e.dst] = e;
			}
		}
		for (int i = 0; i < int(g.size()); ++i) {
			if (i == start)continue;
			int now = i;
			vector<Edge>cycles;
			vector<int>comes(g.size(), -1);
			comes[now] = 0;
			int num = 1;
			while (1) {
				cycles.emplace_back(prev_es[now]);
				now = prev_es[now].src;
				if (comes[now] != -1) {
					cycles = vector < Edge>(cycles.begin() + comes[now], cycles.end());
					reverse(cycles.begin(), cycles.end());
					return cycles;
				}
				else if (now == start) {
					break;
				}
				comes[now] = num++;
			}
		}
		return vector<Edge>(0);
	}
}

//aoj2309をvarifyしたが、正しく復元できているかは不明
pair<Weight, Graph> chu_liu(const Graph&g, const int start, const int e_size) {

	vector<Edge>cycle_edges;
	Weight total_len = 0;
	{
		Graph tree(g.size());
		{
			Graph revg(g.size());


			for (auto es : g) {
				for (auto e : es) {
					revg[e.dst].emplace_back(e.dst, e.src, e.weight, e.id);
				}
			}
			for (int node = 0; node < int(g.size()); ++node) {
				if (node == start)continue;
				else {
					Weight amin = INF;
					Edge min_edge;
					for (auto reve : revg[node]) {
						if (amin > reve.weight) {
							amin = reve.weight;
							min_edge = Edge(reve.dst, reve.src, reve.weight, reve.id);
						}
					}
					if (amin < INF) {
						total_len += min_edge.weight;
						tree[min_edge.src].emplace_back(min_edge);
					}
				}
			}
		}
		cycle_edges = getcycle::get_cycle(tree, start);
		if (cycle_edges.empty()) {
			return make_pair(total_len, tree);
		}
	}
	vector<bool>node_is_cycle(g.size());

	/*要素数はEdgeの数だけで良い*/
	vector<int>edge_is_cycle(e_size);

	vector<Weight>prev_lens(g.size(), ZERO);

	for (auto ce : cycle_edges) {
		node_is_cycle[ce.src] = true;
		prev_lens[ce.dst] = ce.weight;
	}
	Graph newg(g.size());
	const int compress = cycle_edges[0].src;
	/*要素数はEdgeの数だけで良い*/
	vector<Edge>memo(e_size);
	for (int s = 0; s < int(g.size()); ++s) {
		bool src_is_cycle = node_is_cycle[s];
		for (auto e : g[s]) {
			memo[e.id] = e;
			bool dst_is_cycle = node_is_cycle[e.dst];
			if (src_is_cycle&&dst_is_cycle) {
				continue;
			}
			else if (src_is_cycle) {
				e.src = compress;
			}
			else if (dst_is_cycle) {
				e.weight -= prev_lens[e.dst];
				e.dst = compress;
			}
			newg[e.src].push_back(e);
		}
	}
	auto p = chu_liu(newg, start, e_size);
	Graph compress_tree(p.second);
	Graph ans_tree(g.size());
	for (auto es : compress_tree) {
		for (auto e : es) {
			const Edge prev_edge(memo[e.id]);
			if (node_is_cycle[prev_edge.dst]) {
				for (auto cycle_edge : cycle_edges) {
					if (cycle_edge.dst != prev_edge.dst) {
						ans_tree[cycle_edge.src].emplace_back(cycle_edge);
					}
				}
			}
			ans_tree[prev_edge.src].emplace_back(prev_edge);
		}
	}
	Weight cycle_len = 0;
	for (auto e : cycle_edges) {
		cycle_len += e.weight;
	}
	return make_pair(p.first + cycle_len, ans_tree);
}
int main() {
	int N,M;cin>>N>>M;
	vector<vector<int>>edges(N);
	vector<vector<int>>rev_edges(N);
	for (int i = 0; i < M; ++i) {
		int a,b;cin>>a>>b;
		edges[a].push_back(b);
		rev_edges[b].push_back(a);
	}

	vector<int>ids;
	for (int i = 0; i < N; ++i) {
		if (rev_edges[i].empty()) {
			ids.push_back(i);
		}
	}

	vector<vector<int>>costs;
	for (auto start : ids) {
		costs.push_back(get_costs(edges,rev_edges,start,ids));
	}
	Graph g(ids.size());
	int nid=0;
	for (int i = 0; i < ids.size(); ++i) {
		for (int j = 0; j < ids.size(); ++j) {
			if(i!=j)g[i].push_back(Edge(i,j,costs[i][j],nid++));
		}
	}
	pair<int,vector<int>>anss(make_pair(1e9,vector<int>()));
	for (int i = 0; i < ids.size(); ++i) {
		auto p=chu_liu(g,i,(ids.size())*(ids.size()-1));
		//cout<<p.first<<endl;
		if (anss.first > p.first) {
			anss = make_pair(p.first, vector<int>{i});
		}
		else if (anss.first == p.first) {
			anss.second.push_back(i);
		}
	}
	cout<<anss.second.size()<<" "<<anss.first<<endl;
	
	for (int i = 0; i < anss.second.size(); ++i) {
		cout<<ids[anss.second[i]];
		if(i==anss.second.size()-1)cout<<endl;
		else cout<<" ";
	}
	return 0;
}



Measured memory_bytes: 10848