//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define rep(i, n) for(int i=0; i<n; ++i)
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
using namespace std;
using ll = int64_t;
using ld = long double;
using P = pair<int, int>;
using vs = vector<string>;
using vi = vector<int>;
using vvi = vector<vi>;
template<class T> using PQ = priority_queue<T>;
template<class T> using PQG = priority_queue<T, vector<T>, greater<T> >;
const int INF = 0xccccccc;
const ll LINF = 922337203685477580LL;
template<typename T1, typename T2>
inline bool chmax(T1 &a, T2 b) {return a < b && (a = b, true);}
template<typename T1, typename T2>
inline bool chmin(T1 &a, T2 b) {return a > b && (a = b, true);}
template<typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) { return is >> p.first >> p.second;}
template<typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) { return os << p.first << ' ' << p.second;}

const int N = 310;

//head

int n;
int a[N], cnt[4];
ld _[N][N][N];

ld dfs(int i, int j, int k) {
	if(_[i][j][k] > -0.5) return _[i][j][k];
	ld &res = _[i][j][k] = 0;
	int n_ = i+j+k;
	if(i) res += dfs(i-1, j, k) * i/n_;
	if(j) res += dfs(i+1, j-1, k) * j/n_;
	if(k) res += dfs(i, j+1, k-1) * k/n_;
	if(n_) res += (ld)n/n_;
	return res;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n;
	rep(i, n) cin >> a[i];
	rep(i, n) cnt[a[i]]++;
	rep(i, n+1) rep(j, n+1) rep(k, n+1) _[i][j][k] = -1;
	cout << fixed << setprecision(20) << dfs(cnt[1], cnt[2], cnt[3]) << endl;
}
#include "bits/stdc++.h"

#define REP(i,num) for(int i=0;i<(num);++i)
#define LOOP(i) while(i--)
#define ALL(c) c.begin(),c.end()
#define PRINTALL(c) for(auto pitr=c.begin();pitr!=c.end();++pitr){cout<<*pitr;if(next(pitr,1)!=c.end())cout<<' ';}cout<<endl;
#define PAIRCOMP(c,comp) [](const pair<ll,ll>& lhs,const pair<ll,ll>& rhs){return lhs.c comp rhs.c;}

using namespace std;
using ll = long long;

constexpr ll atcoder_mod = 1e9+7;

template<typename T=int>
T in(){T x; cin >> x; return (x);}
template<typename T=int,typename C=vector<T>>
C vecin(int N){C x(N);REP(i,N){x[i]=in<T>();}return move(x);}

void vout(){cout << endl;}
template<typename Head,typename... Tail>
void vout(Head&& h,Tail&&... t){cout << ' ' << h;vout(forward<Tail>(t)...);}
void out(){cout << endl;}
template<typename Head,typename... Tail>
void out(Head&& h,Tail&&... t){cout << h;vout(forward<Tail>(t)...);}

class ConnectNodeInfo{
	vector<vector<pair<ll,ll>>> graph;
public:
	ConnectNodeInfo(int node_num){
		graph.resize(node_num);
	}
	void AddNonDirectionalConnection(ll u,ll v,ll w){
		graph[u].emplace_back(v,w);
		graph[v].emplace_back(u,w);
	}
	void AddDirectionalConnection(ll u,ll v,ll w){
		graph[u].emplace_back(v,w);
	}
	vector<pair<ll,ll>>& operator[](ll index){
		return graph[index];
	}
	size_t size(){return graph.size();}
};

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	cout<<fixed<<setprecision(10);
	
	int N=in(),M=in();
	ConnectNodeInfo connect(N);
	vector<int> input(N,0);
	REP(i,N-1+M){
		int u=in()-1,v=in()-1;
		connect.AddDirectionalConnection(u,v,1);
		input[v]++;
	}
	
	stack<int> vertex;
	vector<int> sorted;
	REP(i,N){
		if(input[i]==0){
			vertex.push(i);
			break;
		}
	}
	while(!vertex.empty()){
		auto v=vertex.top();
		vertex.pop();
		sorted.push_back(v);
		for(auto& x:connect[v]){
			input[x.first]--;
			if(!input[x.first]) vertex.push(x.first);
		}
	}
	vector<int> parent(N,-1);
	REP(i,N){
		for(auto& x:connect[sorted[i]]){
			parent[x.first] = sorted[i];
		}
	}

	for(auto& x:parent){
		out(x+1);
	}
	return 0;
}
