#include <iostream>
#include<bits/stdc++.h>

using namespace std;

int main()
{
    int n,num=0;
    set<int> mySet;
    cin>>n;
    string s[n];
    for(int i=0; i<n; i++)cin>>s[i];
    for(int i=0; i<n; i++)
    {
        for(int j=i+1; j<n; j++)
        {
            string x="";
            int a = atoi((s[i]+s[j]).c_str());
            int b = atoi((s[j]+s[i]).c_str());
            if((a%3==0 || b%3==0) && mySet.find(i)==mySet.end() && mySet.find(j)==mySet.end())
            {
                num++;
                mySet.insert(i);
                mySet.insert(j);
            }

        }
    }
    cout<<num <<endl;
}

/*2 1 4 3
1 2 3 4

36 28 57 39 66 69 68
28 36 39 57 66 68 69
28 36 39 57 66 68 69

1 2 1 2 1
1 1 2 1 2
1 1 1 2 2
1 1 1 2 2
*/


#include<bits/stdc++.h>
using namespace std;
#define li long long int

li func(li x)
{
	li sum=0;
	while(x)
	{
		li r=x%10;
		sum+=r;
		x=x/10;
	}
	return sum;
}

int main()
{
	li n,i,j;
	cin>>n;
	li a[n],sum[n];
	for(i=0;i<n;i++)
	{
		cin>>a[i];
		sum[i]=func(a[i]);
	}
	li ans=0;
	for(i=0;i<n-1;i++)
	{
		if(sum[i]!=0)
		{
			for(j=i+1;j<n;j++)
			{
				if((sum[i]+sum[j])%3==0)
				{
					ans++;
					sum[j]=sum[i]=0;
					break;
				}
			}
		}
	}
	cout<<ans;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin >> n;
	short niz[n];
	long u;
	for(int i=0;i<n;i++){
		cin >> u;
		niz[i]=u%3;
	}
	int br=0;
	for(int i=0;i<n-1;i++){
		if(niz[i]>=0){
			for(int j=i+1;j<n;j++){
				if((niz[i]+niz[j])%3==0){
					br++;
					niz[j]=-5;
					break;
				}
			}
		}
	}
	cout<<br;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin >> n;
	short niz[n];
	long u;
	for(int i=0;i<n;i++){
		cin >> u;
		niz[i]=u%3;
	}
	int br=0;
	for(int i=0;i<n-1;i++){
		if(niz[i]>=0){
			for(int j=i+1;j<n;j++){
				if(niz[j]>=0){
					if((niz[i]+niz[j])%3==0){
						br++;
						niz[j]=-5;
						break;
					}
				}
			}
		}
	}
	cout<<br;
	return 0;
}


#include <iostream>
#include <array>
#include <vector>
#include <algorithm>
#include <string.h>
#include <set>
#include <math.h>
#include <numeric>
#include <assert.h>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <queue>
using namespace std;
#define ll long long
#define ld long double
#define endl "\n"
const ll inf = 1e9 + 69;
const ld pi = 3.14159265358979323L;
const int N = 1e5 + 5;

void setIn(string s){freopen(s.c_str(), "r", stdin);}
void setOut(string s){freopen(s.c_str(), "w", stdout);}
void unsyncIO(){cin.tie(0) -> sync_with_stdio(0);}
void setIO(string s = ""){
	unsyncIO();
	if(s.size()){
		setIn(s + ".in");
		setOut(s + ".out");
	}
}

int main(){
	setIO();

	int n; cin >> n;
	vector<int> cnt(3, 0);
	for(int x; n --;){
		cin >> x;
		cnt[x % 3] ++;
	}

	cout << min(cnt[1], cnt[2]) + cnt[0] / 2 << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int N = 1e5;
bool visited[N];
int mod(string t, int N)
{
    int r = 0;
    for (int i = 0; i < t.length(); i++)
    {
        r = r * 10 + (t[i] - '0');
        r %= N;
    }
    return r;
}

int main(){
    int n;
    scanf("%d",&n);
    string arr[n];
    for (int i=0;i<n;++i)
        cin>>arr[i];
    int c = 0;
    for (int i=0;i<n;++i){
            if (visited[i])
                continue;
        for (int j = 0;j<n;++j){
            if (i==j || visited[j])
                continue;
            string a = arr[i] + arr[j];
            if (mod(a,3) == 0){
                visited[i]++;
                visited[j]++;
                c++;
                break;
            }
        }
    }
    cout<<c;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int N = 3;
int cnt[N];

int main(){
    int n;
    scanf("%d",&n);
    int a;
    for (int i=0;i<n;++i){
        scanf("%d",&a);
        cnt[a%3]++;
    }
    int ans = cnt[0]/2 + min(cnt[1],cnt[2]);
    printf("%d",ans);
    return 0;
}


// http://codeforces.com/problemset/problem/43/C

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int MAXN = 10000;
int n, ans;

int cnt[3];

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

  for(int i = 0; i < n; i++){
    int in;
    scanf("%d", &in);
    cnt[in % 3]++;
  }

  ans += cnt[0]/2;
  ans += min(cnt[1],cnt[2]);

  printf("%d\n", ans);

  return 0;
}


// http://codeforces.com/problemset/problem/43/C

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int MAXN = 10000;
int n, ans;

int cnt[3];

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

  for(int i = 0; i < n; i++){
    int in;
    scanf("%d", &in);
    cnt[in % 3]++;
  }

  ans += cnt[0]/2;
  ans += min(cnt[1],cnt[2]);

  print("%d\n", ans);

  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define all(v) v.begin(), v.end()
#define rep(i,n)for(ll i=0;i<n;i++)
#define repd(i,a,b) for(ll i=a;i>=b;--i)
#define maxx 1000001
#define int long long
#define f first
#define s second

const int mod = 1e9+7,N=1e3+1;
int vis[N];
vector<int> arr[N];
map<char,int>m;
int a[N];

signed main()
{
 int n,m=0,p=0,q=0;
 cin>>n;
 rep(i,n){
    int x;
    cin>>x;
    if(x%3==0)m++;
    else if(x%3==1)p++;
    else q++;
}
 int nis=m/2+(min(p,q));
 cout<<nis;
 return 0;
}


#include<bits/stdc++.h>
//#define RIP
using namespace std;

typedef long long int ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int,int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> pll;
typedef vector<pii> vii;
typedef vector<pll> vll;

#define PB push_back
#define F first
#define S second
#define MP make_pair
#define endl '\n'
#define mx1 100005
#define mx2 200005
#define mx3 300005
#define WHITE 0
#define GRAY 1
#define BLACK -1
#define x 10000005

const double PI = acos(-1);
const double eps = 1e-9;
const int inf = 2000000000;
const ll infLL = 90000000000000000;
const int MOD = 1000000007;
int MOD1 = 1000000007;
int MOD2 = 1000000009;
//#define harmonic(n) 0.57721566490153286l+log(n)

#define mem(a,b) memset(a, b, sizeof(a) )
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) (a*(b/gcd(a,b)))
#define sqr(a) ((a) * (a))

#define optimize() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

typedef vector<int>::iterator vit;
typedef set<int>::iterator sit;

inline bool checkBit(ll n, ll i) { return n&(1LL<<i); }
inline ll setBit(ll n, ll i) { return n|(1LL<<i);; }
inline ll resetBit(ll n, ll i) { return n&(~(1LL<<i)); }

int dx[] = {0, 0, +1, -1};
int dy[] = {+1, -1, 0, 0};
//int dx[] = {+1, 0, -1, 0, +1, +1, -1, -1};
//int dy[] = {0, +1, 0, -1, +1, -1, +1, -1};

inline bool EQ(double a, double b) { return fabs(a-b) < 1e-9; }
inline bool isLeapYear(ll year) { return (year%400==0) || (year%4==0 && year%100!=0); }
inline void normal(ll &a) { a %= MOD; (a < 0) && (a += MOD); }
inline ll modMul(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); return (a*b)%MOD; }
inline ll modAdd(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); return (a+b)%MOD; }
inline ll modSub(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); a -= b; normal(a); return a; }
inline ll modPow(ll b, ll p) { ll r = 1LL; while(p) { if(p&1) r = modMul(r, b); b = modMul(b, b); p >>= 1LL; } return r; }
inline ll modDiv(ll a, ll b) { return modMul(a, modPow(b, MOD-2)); }

bool converter( string a )
{
    ll i , mul = 1 , r , t ,ans = 0LL;

    if( a.length() == 0 )return 0;

    for( i = a.length() - 1 ; i >= 0 ; i-- ){
        t = a[i] - '0';
        r = t%10;
        ans += (mul*r);
        mul = mul*10;
    }
    return (ans % 3 == 0 ) ? 1 : 0;
}

//
//debug
#ifdef RIP
template < typename F, typename S >
ostream& operator << ( ostream& os, const pair< F, S > & p ) {
            return os << "(" << p.first << ", " << p.second << ")";
}

template < typename T >
ostream &operator << ( ostream & os, const vector< T > &v ) {
            os << "{";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "}";
}

template < typename T >
ostream &operator << ( ostream & os, const set< T > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "]";
}

template < typename T >
ostream &operator << ( ostream & os, const multiset< T > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "]";
}

template < typename F, typename S >
ostream &operator << ( ostream & os, const map< F, S > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << it -> first << " = " << it -> second ;
                                            }
                    return os << "]";
}

#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0)

void faltu () {
            cerr << endl;
}

template <typename T>
void faltu( T a[], int n ) {
            for(int i = 0; i < n; ++i) cerr << a[i] << ' ';
                cerr << endl;
}

template <typename T, typename ... hello>
void faltu( T arg, const hello &... rest) {
            cerr << arg << ' ';
                faltu(rest...);
}
#else
#define dbg(args...)
#endif  //RIP

ll a[mx1];
int main()
{
    optimize();
   //freopen("input.txt" , "r" , stdin );

    ll n , i , j , k , f , ans = 0LL , t = 0LL , tw = 0LL, o = 1LL ;
    cin >> n ;
    for( i = 1 ; i <= n ; i++ ){
        cin >> f;
        if( f % 3 == 0 ) t++;
        if( f % 3 == 2 ) tw++;
        else o++;
    }

    ans += ( t/2 );
    ans += min( o , tw );

    cout << ans;

    return 0;
}


#include<bits/stdc++.h>
//#define RIP
using namespace std;

typedef long long int ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int,int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> pll;
typedef vector<pii> vii;
typedef vector<pll> vll;

#define PB push_back
#define F first
#define S second
#define MP make_pair
#define endl '\n'
#define mx1 100005
#define mx2 200005
#define mx3 300005
#define WHITE 0
#define GRAY 1
#define BLACK -1
#define x 10000005

const double PI = acos(-1);
const double eps = 1e-9;
const int inf = 2000000000;
const ll infLL = 90000000000000000;
const int MOD = 1000000007;
int MOD1 = 1000000007;
int MOD2 = 1000000009;
//#define harmonic(n) 0.57721566490153286l+log(n)

#define mem(a,b) memset(a, b, sizeof(a) )
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) (a*(b/gcd(a,b)))
#define sqr(a) ((a) * (a))

#define optimize() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

typedef vector<int>::iterator vit;
typedef set<int>::iterator sit;

inline bool checkBit(ll n, ll i) { return n&(1LL<<i); }
inline ll setBit(ll n, ll i) { return n|(1LL<<i);; }
inline ll resetBit(ll n, ll i) { return n&(~(1LL<<i)); }

int dx[] = {0, 0, +1, -1};
int dy[] = {+1, -1, 0, 0};
//int dx[] = {+1, 0, -1, 0, +1, +1, -1, -1};
//int dy[] = {0, +1, 0, -1, +1, -1, +1, -1};

inline bool EQ(double a, double b) { return fabs(a-b) < 1e-9; }
inline bool isLeapYear(ll year) { return (year%400==0) || (year%4==0 && year%100!=0); }
inline void normal(ll &a) { a %= MOD; (a < 0) && (a += MOD); }
inline ll modMul(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); return (a*b)%MOD; }
inline ll modAdd(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); return (a+b)%MOD; }
inline ll modSub(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); a -= b; normal(a); return a; }
inline ll modPow(ll b, ll p) { ll r = 1LL; while(p) { if(p&1) r = modMul(r, b); b = modMul(b, b); p >>= 1LL; } return r; }
inline ll modDiv(ll a, ll b) { return modMul(a, modPow(b, MOD-2)); }

bool converter( string a )
{
    ll i , mul = 1 , r , t ,ans = 0LL;

    if( a.length() == 0 )return 0;

    for( i = a.length() - 1 ; i >= 0 ; i-- ){
        t = a[i] - '0';
        r = t%10;
        ans += (mul*r);
        mul = mul*10;
    }
    return (ans % 3 == 0 ) ? 1 : 0;
}

//
//debug
#ifdef RIP
template < typename F, typename S >
ostream& operator << ( ostream& os, const pair< F, S > & p ) {
            return os << "(" << p.first << ", " << p.second << ")";
}

template < typename T >
ostream &operator << ( ostream & os, const vector< T > &v ) {
            os << "{";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "}";
}

template < typename T >
ostream &operator << ( ostream & os, const set< T > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "]";
}

template < typename T >
ostream &operator << ( ostream & os, const multiset< T > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "]";
}

template < typename F, typename S >
ostream &operator << ( ostream & os, const map< F, S > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << it -> first << " = " << it -> second ;
                                            }
                    return os << "]";
}

#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0)

void faltu () {
            cerr << endl;
}

template <typename T>
void faltu( T a[], int n ) {
            for(int i = 0; i < n; ++i) cerr << a[i] << ' ';
                cerr << endl;
}

template <typename T, typename ... hello>
void faltu( T arg, const hello &... rest) {
            cerr << arg << ' ';
                faltu(rest...);
}
#else
#define dbg(args...)
#endif  //RIP

int main()
{
    optimize();
   //freopen("input.txt" , "r" , stdin );

    ll n , i , j , k , f , ans = 0LL , t = 0LL , tw = 0LL, o = 0LL ;
    cin >> n ;
    for( i = 1 ; i <= n ; i++ ){
        cin >> f;
        ll k = f;
        f = 0LL;
        while( k ){
            f += ( k % 10 );
            k /= 10;
        }
        f %= 3;
        if( f == 0 ) t++;
        if( f== 2 ) tw++;
        else o++;
    }

    ans += ( t/2 );
    ans += min( o , tw );

    cout << ans;

    return 0;
}


#include<bits/stdc++.h>
//#define RIP
using namespace std;

typedef long long int ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int,int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> pll;
typedef vector<pii> vii;
typedef vector<pll> vll;

#define PB push_back
#define F first
#define S second
#define MP make_pair
#define endl '\n'
#define mx1 100005
#define mx2 200005
#define mx3 300005
#define WHITE 0
#define GRAY 1
#define BLACK -1
#define x 10000005

const double PI = acos(-1);
const double eps = 1e-9;
const int inf = 2000000000;
const ll infLL = 90000000000000000;
const int MOD = 1000000007;
int MOD1 = 1000000007;
int MOD2 = 1000000009;
//#define harmonic(n) 0.57721566490153286l+log(n)

#define mem(a,b) memset(a, b, sizeof(a) )
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) (a*(b/gcd(a,b)))
#define sqr(a) ((a) * (a))

#define optimize() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

typedef vector<int>::iterator vit;
typedef set<int>::iterator sit;

inline bool checkBit(ll n, ll i) { return n&(1LL<<i); }
inline ll setBit(ll n, ll i) { return n|(1LL<<i);; }
inline ll resetBit(ll n, ll i) { return n&(~(1LL<<i)); }

int dx[] = {0, 0, +1, -1};
int dy[] = {+1, -1, 0, 0};
//int dx[] = {+1, 0, -1, 0, +1, +1, -1, -1};
//int dy[] = {0, +1, 0, -1, +1, -1, +1, -1};

inline bool EQ(double a, double b) { return fabs(a-b) < 1e-9; }
inline bool isLeapYear(ll year) { return (year%400==0) || (year%4==0 && year%100!=0); }
inline void normal(ll &a) { a %= MOD; (a < 0) && (a += MOD); }
inline ll modMul(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); return (a*b)%MOD; }
inline ll modAdd(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); return (a+b)%MOD; }
inline ll modSub(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); a -= b; normal(a); return a; }
inline ll modPow(ll b, ll p) { ll r = 1LL; while(p) { if(p&1) r = modMul(r, b); b = modMul(b, b); p >>= 1LL; } return r; }
inline ll modDiv(ll a, ll b) { return modMul(a, modPow(b, MOD-2)); }

bool converter( string a )
{
    ll i , mul = 1 , r , t ,ans = 0LL;

    if( a.length() == 0 )return 0;

    for( i = a.length() - 1 ; i >= 0 ; i-- ){
        t = a[i] - '0';
        r = t%10;
        ans += (mul*r);
        mul = mul*10;
    }
    return (ans % 3 == 0 ) ? 1 : 0;
}

//
//debug
#ifdef RIP
template < typename F, typename S >
ostream& operator << ( ostream& os, const pair< F, S > & p ) {
            return os << "(" << p.first << ", " << p.second << ")";
}

template < typename T >
ostream &operator << ( ostream & os, const vector< T > &v ) {
            os << "{";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "}";
}

template < typename T >
ostream &operator << ( ostream & os, const set< T > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "]";
}

template < typename T >
ostream &operator << ( ostream & os, const multiset< T > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "]";
}

template < typename F, typename S >
ostream &operator << ( ostream & os, const map< F, S > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << it -> first << " = " << it -> second ;
                                            }
                    return os << "]";
}

#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0)

void faltu () {
            cerr << endl;
}

template <typename T>
void faltu( T a[], int n ) {
            for(int i = 0; i < n; ++i) cerr << a[i] << ' ';
                cerr << endl;
}

template <typename T, typename ... hello>
void faltu( T arg, const hello &... rest) {
            cerr << arg << ' ';
                faltu(rest...);
}
#else
#define dbg(args...)
#endif  //RIP

ll a[mx1];
int main()
{
    optimize();
   //freopen("input.txt" , "r" , stdin );

    ll n , i , j , k , f , ans = 0LL , t = 0LL , tw = 0LL, o = 1LL ;
    cin >> n ;
    for( i = 1 ; i <= n ; i++ ){
        cin >> f;
        ll k = f;
        f = 0LL;
        while( k > 0 ){
            f += ( k % 10 );
            k /= 10;
        }
        if( f % 3 == 0 ) t++;
        if( f % 3 == 2 ) tw++;
        else o++;
    }

    ans += ( t/2 );
    ans += min( o , tw );

    cout << ans;

    return 0;
}


#include<bits/stdc++.h>
//#define RIP
using namespace std;

typedef long long int ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int,int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> pll;
typedef vector<pii> vii;
typedef vector<pll> vll;

#define PB push_back
#define F first
#define S second
#define MP make_pair
#define endl '\n'
#define mx1 100005
#define mx2 200005
#define mx3 300005
#define WHITE 0
#define GRAY 1
#define BLACK -1
#define x 10000005

const double PI = acos(-1);
const double eps = 1e-9;
const int inf = 2000000000;
const ll infLL = 90000000000000000;
const int MOD = 1000000007;
int MOD1 = 1000000007;
int MOD2 = 1000000009;
//#define harmonic(n) 0.57721566490153286l+log(n)

#define mem(a,b) memset(a, b, sizeof(a) )
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) (a*(b/gcd(a,b)))
#define sqr(a) ((a) * (a))

#define optimize() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

typedef vector<int>::iterator vit;
typedef set<int>::iterator sit;

inline bool checkBit(ll n, ll i) { return n&(1LL<<i); }
inline ll setBit(ll n, ll i) { return n|(1LL<<i);; }
inline ll resetBit(ll n, ll i) { return n&(~(1LL<<i)); }

int dx[] = {0, 0, +1, -1};
int dy[] = {+1, -1, 0, 0};
//int dx[] = {+1, 0, -1, 0, +1, +1, -1, -1};
//int dy[] = {0, +1, 0, -1, +1, -1, +1, -1};

inline bool EQ(double a, double b) { return fabs(a-b) < 1e-9; }
inline bool isLeapYear(ll year) { return (year%400==0) || (year%4==0 && year%100!=0); }
inline void normal(ll &a) { a %= MOD; (a < 0) && (a += MOD); }
inline ll modMul(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); return (a*b)%MOD; }
inline ll modAdd(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); return (a+b)%MOD; }
inline ll modSub(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); a -= b; normal(a); return a; }
inline ll modPow(ll b, ll p) { ll r = 1LL; while(p) { if(p&1) r = modMul(r, b); b = modMul(b, b); p >>= 1LL; } return r; }
inline ll modDiv(ll a, ll b) { return modMul(a, modPow(b, MOD-2)); }

bool converter( string a )
{
    ll i , mul = 1 , r , t ,ans = 0LL;

    if( a.length() == 0 )return 0;

    for( i = a.length() - 1 ; i >= 0 ; i-- ){
        t = a[i] - '0';
        r = t%10;
        ans += (mul*r);
        mul = mul*10;
    }
    return (ans % 3 == 0 ) ? 1 : 0;
}

//
//debug
#ifdef RIP
template < typename F, typename S >
ostream& operator << ( ostream& os, const pair< F, S > & p ) {
            return os << "(" << p.first << ", " << p.second << ")";
}

template < typename T >
ostream &operator << ( ostream & os, const vector< T > &v ) {
            os << "{";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "}";
}

template < typename T >
ostream &operator << ( ostream & os, const set< T > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "]";
}

template < typename T >
ostream &operator << ( ostream & os, const multiset< T > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "]";
}

template < typename F, typename S >
ostream &operator << ( ostream & os, const map< F, S > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << it -> first << " = " << it -> second ;
                                            }
                    return os << "]";
}

#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0)

void faltu () {
            cerr << endl;
}

template <typename T>
void faltu( T a[], int n ) {
            for(int i = 0; i < n; ++i) cerr << a[i] << ' ';
                cerr << endl;
}

template <typename T, typename ... hello>
void faltu( T arg, const hello &... rest) {
            cerr << arg << ' ';
                faltu(rest...);
}
#else
#define dbg(args...)
#endif  //RIP

vector < string > v;
map < ll , ll > mp;

int main()
{
    optimize();
   // freopen("input.txt" , "r" , stdin );

    ll n , i , j , k , f , ans = 0LL ;
    string a;
    cin >> n ;
    for( i = 1 ; i <= n ; i++ ){
        cin >> a;
        v.push_back(a);
    }
    for( i = 0 ; i < n ; i++ ){
        string temp;
        f = 0;
        for( j = i + 1 ; j < n && f == 0 ; j++ ){
             temp = v[i];
             if( !mp[i] && !mp[j] ){
             for( k = 0 ; k < v[j].size() ; k++){
                temp += v[j][k];
             }
             ll flag = converter( temp );
             if( flag ){
                mp[j] = 1;
                mp[i] = 1;
                f = 0;
                ans++;
             }
            }
        }
    }

    cout << ans;

    return 0;
}


#include<bits/stdc++.h>
//#define RIP
using namespace std;

typedef long long int ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int,int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> pll;
typedef vector<pii> vii;
typedef vector<pll> vll;

#define PB push_back
#define F first
#define S second
#define MP make_pair
#define endl '\n'
#define mx1 100005
#define mx2 200005
#define mx3 300005
#define WHITE 0
#define GRAY 1
#define BLACK -1
#define x 10000005

const double PI = acos(-1);
const double eps = 1e-9;
const int inf = 2000000000;
const ll infLL = 90000000000000000;
const int MOD = 1000000007;
int MOD1 = 1000000007;
int MOD2 = 1000000009;
//#define harmonic(n) 0.57721566490153286l+log(n)

#define mem(a,b) memset(a, b, sizeof(a) )
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) (a*(b/gcd(a,b)))
#define sqr(a) ((a) * (a))

#define optimize() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

typedef vector<int>::iterator vit;
typedef set<int>::iterator sit;

inline bool checkBit(ll n, ll i) { return n&(1LL<<i); }
inline ll setBit(ll n, ll i) { return n|(1LL<<i);; }
inline ll resetBit(ll n, ll i) { return n&(~(1LL<<i)); }

int dx[] = {0, 0, +1, -1};
int dy[] = {+1, -1, 0, 0};
//int dx[] = {+1, 0, -1, 0, +1, +1, -1, -1};
//int dy[] = {0, +1, 0, -1, +1, -1, +1, -1};

inline bool EQ(double a, double b) { return fabs(a-b) < 1e-9; }
inline bool isLeapYear(ll year) { return (year%400==0) || (year%4==0 && year%100!=0); }
inline void normal(ll &a) { a %= MOD; (a < 0) && (a += MOD); }
inline ll modMul(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); return (a*b)%MOD; }
inline ll modAdd(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); return (a+b)%MOD; }
inline ll modSub(ll a, ll b) { a %= MOD, b %= MOD; normal(a), normal(b); a -= b; normal(a); return a; }
inline ll modPow(ll b, ll p) { ll r = 1LL; while(p) { if(p&1) r = modMul(r, b); b = modMul(b, b); p >>= 1LL; } return r; }
inline ll modDiv(ll a, ll b) { return modMul(a, modPow(b, MOD-2)); }

bool converter( string a )
{
    ll i , mul = 1 , r , t ,ans = 0LL;

    if( a.length() == 0 )return 0;

    for( i = a.length() - 1 ; i >= 0 ; i-- ){
        t = a[i] - '0';
        r = t%10;
        ans += (mul*r);
        mul = mul*10;
    }
    return (ans % 3 == 0 ) ? 1 : 0;
}

//
//debug
#ifdef RIP
template < typename F, typename S >
ostream& operator << ( ostream& os, const pair< F, S > & p ) {
            return os << "(" << p.first << ", " << p.second << ")";
}

template < typename T >
ostream &operator << ( ostream & os, const vector< T > &v ) {
            os << "{";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "}";
}

template < typename T >
ostream &operator << ( ostream & os, const set< T > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "]";
}

template < typename T >
ostream &operator << ( ostream & os, const multiset< T > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << *it;
                                            }
                    return os << "]";
}

template < typename F, typename S >
ostream &operator << ( ostream & os, const map< F, S > &v ) {
            os << "[";
                for(auto it = v.begin(); it != v.end(); ++it) {
                                if( it != v.begin() ) os << ", ";
                                        os << it -> first << " = " << it -> second ;
                                            }
                    return os << "]";
}

#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0)

void faltu () {
            cerr << endl;
}

template <typename T>
void faltu( T a[], int n ) {
            for(int i = 0; i < n; ++i) cerr << a[i] << ' ';
                cerr << endl;
}

template <typename T, typename ... hello>
void faltu( T arg, const hello &... rest) {
            cerr << arg << ' ';
                faltu(rest...);
}
#else
#define dbg(args...)
#endif  //RIP

int main()
{
    optimize();
   //freopen("input.txt" , "r" , stdin );

    ll n , i , j , k , f , ans = 0LL , t = 0LL , tw = 0LL, o = 0LL ;
    cin >> n ;
    for( i = 1 ; i <= n ; i++ ){
        cin >> f;
        ll k = f;
        f = 0LL;
        while( k ){
            f += ( k % 10 );
            k /= 10;
        }
        f %= 3;
        if( f == 0 ) t++;
        else if( f == 2 ) tw++;
        else o++;
    }

    ans += ( t/2 );
    ans += min( o , tw );

    cout << ans;

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

using ll = long long;

int main() {
	int n;
	cin >> n;
	vector<int> freq(3);
	for (int i = 0; i < n; i++) {
		int x;
		cin >> x;
		int sum = 0;
		while (x > 0) {
			sum += x % 10;
			x /= 10;
		}
		freq[sum % 3]++;

	}
	int ans = freq[0] / 2;
	ans += min(freq[1], freq[2]);
	cout << ans;

	cin.get();
	cin.get();
	return 0;
}


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

int main()
{
   int n;
   cin>>n;
   long long x,a=0,b=0,c=0;
    for(int i=0;i<n;i++)
    {
        cin>>x;
        if(x%3==0)a++;
        else if(x%3==1)b++;
        else if(x%3==2)c++;
    }
    if(b>c) cout<<c+a/2<<endl;
    else
    cout<<b+a/2<<endl;
    return 0;
}


#include <iostream>

using namespace std;

int main()
{
   int n,cnt=0;
   cin>>n;
   long long arr[n];
    for(int i=0;i<n;i++)
    {
        cin>>arr[i];
    }
    for(int j=0;j<n;j++)
    {
      if(arr[j]==arr[j-1])cnt++;
      else
        cnt=0;
    }
    cout<<cnt/3+1<<endl;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

int vis[500000];
long long  ans, a, b, c;
char t[5000][5000];

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n, x;
	cin >> n;
	for(int i = 0;i < n;i++){
		cin >> x;
		if(x%3 == 0)a++;
		else if(x%3 == 1)b++;
		else c++;
	}
	ans = (a/2)+min(b, c);
	cout << ans << endl;
}


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

int mod(string& s){
    int x=0,n=s.length();
    for(int i=0;i<n;i++){
        x+=(s[i]-'0')%3;
    }
    return x%3;
}

int main(){
    int n;
    cin>>n;
    int a[3]={0};
    string s;
    for(int i=0;i<n;i++){
        cin>>s;cout<<mod(s)<<endl;
        a[mod(s)]++;
    }
    cout<<a[0]/2+min(a[1],a[2]);
    return 0;
}


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

int mod(string& s){
    int x=0,n=s.length();
    for(int i=0;i<n;i++){
        x+=(s[i]-'0')%3;
    }
    return x%3;
}

int main(){
    int n;
    cin>>n;
    int a[3]={0};
    string s;
    for(int i=0;i<n;i++){
        cin>>s;//cout<<mod(s)<<endl;
        a[mod(s)]++;
    }
    cout<<a[0]/2+min(a[1],a[2]);
    return 0;
}


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

int mod(string& s){
    int x=0,n=s.length();
    for(int i=0;i<n;i++){
        x+=(s[i]-'0')%3;
    }
    return x%3;
}

int main(){
    int n;
    cin>>n;
    int a[3]={0};
    string s;
    for(int i=0;i<n;i++){
        cin>>s;
        a[mod(s)]++;
    }
    cout<<a[0]/2+min(a[0],a[1]);
    return 0;
}


#include <iostream>
#include <stdio.h>
#include <bits/stdc++.h>
#include <string.h>
#include <math.h>
#define lld long long int
#define ld long int
#define mod 1000000007
#define pb push_back
#define ump unordered_map
#define fast1 ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0);
#define fors(i,n) for(int i=0;i<n;i++)
#define forse(i,a,b) for(lld i=a;i<b;i++)
#define forsei(i,a,b) for(lld i=a;i>=b;i--)
#define gogprnt cout<<"Case #"<<x<<": ";
#define Sortdes(ar,n) sort(ar,n,greater<lld>());
using namespace std;
//lld mypower(lld x, lld n){	if (n == 0)	return 1;	if (n & 1) 	return (((x * mypower(x, n / 2))%mod) * (mypower(x, n / 2)%mod)%mod);return (((mypower(x, n / 2))%mod) * (mypower(x, n / 2)%mod))%mod;}
//int gcd(int a,int b){ if(b==1 || a==1)   return 1;    if(b%a==0)    return a;    return(gcd(b%a,a));}
//lld modinv(lld a) { lld g = gcd(a, mod); if (g != 1) return -1;else{  return mypower(a, mod-2)%mod; } }
//(a/b)%m==((a%m)*(modinv(b)%m));
//a%m=(a+m)%m in order to avoid -ve no
//bool cmp(const pair<lld,lld> &a,const pair<lld,lld> &b) return (a.first()>b.first());
// vector<vector<lld>> adj(1e6+1);
// ump<lld,lld> vis,mp;lld od=3,ev=2;
// void dfs(lld j)
// {vis[j]=1;
// for (auto i : adj[j])
// {
//   if(!vis[i])
//   {
//     if(mp[j]==1) { mp[i]=2;}
//     else {mp[i]=1;}
//     dfs(i);
//   }

// }}
void solve()
{
    lld n,ans=0,sm=0,flag=0,t=0;//string s,s1;
     cin>>n;
     lld ar[n];
     fors(i,n) cin>>ar[i];
     fors(i,n)
     {lld p=ar[i],sm=0;
         while(p!=0)
         {
           sm+=p%10;
           p/=10;
         }
        if(!(sm%3)) ans++;
        else if(sm%3==1) flag++;
        else t++;
     }
     ans/=2;
     ans+=min(t,flag);
   cout<<ans<<endl;

}
int main() {fast1;
//int x=1,t;cin>>t;while(t--)
	 solve();//x++;}
	return 0;
}


#include <iostream>

using namespace std;

int main()
{

    int n, t = 0;
    cin >> n;
    int arr[n];

    for (int i = 0; i < n; i++)
        cin >> arr[i];

    for (int i = 1; i < n; i++)
    {
        if (arr[i-1] && arr[i] && (arr[i-1] + arr[i]) % 3 == 0)
        {
            t++; arr[i-1] = 0; arr[i] = 0;
        }
    }

    cout << t << flush;
}


#include <iostream>

using namespace std;

int main()
{

    // lucky ticket --------------------------------------------------------
    int n, t = 0;
    cin >> n;
    long long arr[n];

    for (int i = 0; i < n; i++)
        cin >> arr[i];

    for (int i = 0; i < n; i++)
    {
        for (int k = 0; k < n; k++)
        if (arr[i] && arr[k] && (arr[i] + arr[k]) % 3 == 0)
        {
            if (i == k)
                continue;
            t++;
            arr[k] = 0;
            arr[i] = 0;
        }
    }

    cout << t << flush;

}


#include <iostream>

using namespace std;

int main()
{

    int n, t = 0;
    cin >> n;
    int arr[n];

    for (int i = 0; i < n; i++)
        cin >> arr[i];

    for (int i = 1; i < n; i++)
    {
        if (arr[i-1] % 3 == arr[i] % 3 == (arr[i-1] + arr[i]) % 3 == 0)
        {
            t++; arr[i-1] = 0; arr[i] = 0;
        }
    }

    cout << t << flush;
}


#include <bits/stdc++.h>
using namespace std;
#define VI vector<int>
#define VL vector<long long>
#define VIP vector<pair<int, int>>
#define VLP vector<pair<long long, long long>>
#define SIZE(obj) (int(obj.size()))
#define SORT(x) sort(x.begin(), x.end())
#define wq int q; cin >> q; while(q--)
#define pb push_back
const double PI = 3.1415926535;
long long powi(long long base, int p) { long long res = 1; while(p--) res *= base; return res;}
long long gcd(long long a, long long b) {return b == 0 ? a : gcd(b, a%b);}
bool is_vowel(char c) {c=tolower(c); return c=='a'||c=='e'||c=='o'||c=='i'||c=='u'||c=='y';}

int main() { ios_base::sync_with_stdio(0); cin.tie(0);
    // freopen("input.txt","r",stdin);
	// freopen("output.txt","w",stdout);
    map<int, int> dict;
    int n;
    cin >> n;
    for (int i=0, a;i<n;i++) {
        cin >> a;
        dict[a % 3]++;
    }
    cout << dict[0]/2 + min(dict[1], dict[2]);
    return 0;
}


import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] arg) {
		FastScanner scan = null;
		PrintWriter out = null;
		try{
			scan = new FastScanner(new FileInputStream("input.txt"));
			out = new PrintWriter(new FileOutputStream("output.txt"));
		}catch(FileNotFoundException e){
			scan = new FastScanner(System.in);
			out = new PrintWriter(System.out);
		}
		int n = scan.nextInt();
		int[] mods = new int[3];
		for(int i = 0; i < n; i++){
			int t = scan.nextInt();
			mods[t%3]++;
		}
		out.println(mods[0]/2 + Math.min(mods[1], mods[2]));
		out.close();
	}

	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner(InputStream is) {
			try {
				br = new BufferedReader(new InputStreamReader(is));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (Exception e) {
					return null;
				}
			}
			return st.nextToken();
		}

		String nextLine() {
	        try {
	            return br.readLine();
	        }
	        catch (Exception e) {
	            return null;
	        }
	    }
		int nextInt() {
			return Integer.parseInt(next());
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		double nextDouble() {
			return Double.valueOf(next());
		}
	}
}


import java.io.*;
import java.util.*;
public class LuckyTickets
{
    public static void main(String[] args) throws IOException
    {
        //Locale.setDefault (Locale.US);
        Reader in = new Reader();
        StringBuilder out = new StringBuilder();
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        int n, sum, temp, count;
        String half;
        for (int i = 0; i < 1; i++) {
            n = in.nextInt();
            map.clear();
            for (int j = 0; j < n; j++) {
                sum = 0;
                half = in.next();
                for (int k = 0; k < half.length(); k++)
                    sum += half.charAt(k)-'0';
                temp = 1;
                if(map.containsKey(sum))
                    temp += map.get(sum);
                map.put(sum, temp);
            }
            count = 0;
            for(Integer key : map.keySet()){
                if(map.get(key) == 0) continue;
                for (Integer key2 : map.keySet()) {
                    if((key+key2)%3 != 0 || map.get(key2) == 0 )continue;
                    if(key == key2){
                        while(map.get(key) > 1 ){
                            temp = map.get(key)-2;
                            map.put(key, temp);
                            count++;
                        }
                    }
                    else{
                        temp = map.get(key2)-1;
                        map.put(key2, temp);
                        temp = map.get(key)-1;
                        map.put(key, temp);
                        count++;
                        break;
                    }
                }

            }
            System.out.println(count);

        }
    }
    static class  Reader
    {
        BufferedReader br;
        StringTokenizer st;
        Reader() { // To read from the standard input
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        Reader(int i) throws IOException { // To read from a file
            br = new BufferedReader(new FileReader("Sample Input.txt"));
        }
       String next() throws IOException {
          while (st == null || !st.hasMoreTokens())
             st = new StringTokenizer(br.readLine());
          return st.nextToken();
       }
       int nextInt() throws IOException { return Integer.parseInt(next()); }
       long nextLong() throws IOException { return Long.parseLong(next()); }
       double nextDouble() throws IOException { return Double.parseDouble(next()); }
       String nextLine() throws IOException { return br.readLine(); }
    }

}


import java.io.*;
import java.util.*;
public class luckyyy
{
    public static void main(String[] args) throws IOException
    {
        Reader in = new Reader();
        int n, count;
        int[] grps;
        for (int i = 0; i < 1; i++) {
            n = in.nextInt();
            grps = new int[3];
            for (int j = 0; j < n; j++)
                grps[in.nextInt()%3]++;

            count = Math.min(grps[1], grps[2])+(grps[0]/2);

            System.out.println(count);

        }
    }
    static class  Reader
    {
        BufferedReader br;
        StringTokenizer st;
        Reader() { // To read from the standard input
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        Reader(int i) throws IOException { // To read from a file
            br = new BufferedReader(new FileReader("Sample Input.txt"));
        }
       String next() throws IOException {
          while (st == null || !st.hasMoreTokens())
             st = new StringTokenizer(br.readLine());
          return st.nextToken();
       }
       int nextInt() throws IOException { return Integer.parseInt(next()); }
       long nextLong() throws IOException { return Long.parseLong(next()); }
       double nextDouble() throws IOException { return Double.parseDouble(next()); }
       String nextLine() throws IOException { return br.readLine(); }
    }

}


import java.io.*;
import java.util.*;
public class LuckyTickets
{
    public static void main(String[] args) throws IOException
    {
        //Locale.setDefault (Locale.US);
        Reader in = new Reader();
        StringBuilder out = new StringBuilder();
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        int n, sum, temp, count;
        String half;
        for (int i = 0; i < 1; i++) {

            n = in.nextInt();
            map.clear();
//            System.out.println(n);
            half = "";
            for (int j = 0; j < n; j++) {
                sum = 0;

                half = in.next();
//                System.out.println(half);
                for (int k = 0; k < half.length(); k++)
                    sum += half.charAt(k)-'0';
                temp = 1;
                if(map.containsKey(sum))
                    temp += map.get(sum);
                map.put(sum, temp);
            }
//            System.out.println("ast "+half);
            count = 0;
            for(Integer key : map.keySet()){
                if(map.get(key) == 0) continue;
                for (Integer key2 : map.keySet()) {
                    if(key == key2 || (key+key2)%3 != 0 || map.get(key2) == 0 )continue;

                    count++;
                    temp = map.get(key2)-1;
                    map.put(key2, temp);
                    temp = map.get(key)-1;
                    map.put(key, temp);
                    break;

                }
            }
            System.out.println(count);

//            for (int j = 0; j < 10000; j++) {
//                out.append(j+" ");
//            }
//            System.out.println(out);
        }
    }
    static class  Reader
    {
        BufferedReader br;
        StringTokenizer st;
        Reader() { // To read from the standard input
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        Reader(int i) throws IOException { // To read from a file
            br = new BufferedReader(new FileReader("Sample Input.txt"));
        }
       String next() throws IOException {
          while (st == null || !st.hasMoreTokens())
             st = new StringTokenizer(br.readLine());
          return st.nextToken();
       }
       int nextInt() throws IOException { return Integer.parseInt(next()); }
       long nextLong() throws IOException { return Long.parseLong(next()); }
       double nextDouble() throws IOException { return Double.parseDouble(next()); }
       String nextLine() throws IOException { return br.readLine(); }
    }

}


import java.util.ArrayList;
import java.util.Scanner;

public class P43C {
    public P43C() {
        Scanner sc = new Scanner (System.in);
        int n = sc.nextInt();
        ArrayList<Integer> pieces = new ArrayList<>();
        @SuppressWarnings("unchecked")
        ArrayList<Integer>[] digitSum = new ArrayList[3];
        digitSum[0] = new ArrayList<Integer>();
        digitSum[1] = new ArrayList<Integer>();
        digitSum[2] = new ArrayList<Integer>();
        for (int i = 0; i < n; i++){
            int k = sc.nextInt();
            pieces.add(k);
            int ds = digitSum(k);
            if (ds % 3 == 0){
                digitSum[0].add(k);
            }
            else if (ds % 3 == 1){
                digitSum[1].add(k);
            }
            else if (ds % 3 == 2){
                digitSum[2].add(k);
            }
        }
        sc.close();

        int min = digitSum[0].size()/2;
        min += Math.min(digitSum[1].size(), digitSum[2].size());
        System.out.println(min);
    }

    int digitSum (int x){
        if (x == 0){
            return 0;
        }
        else {
            return x % 10 + digitSum(x/10);
        }
    }

    public static void main (String []args){
        new P43C();
    }
}


import java.io.*;
import java.util.*;
public class j
{
public static void main(String a[])throws IOException
{
BufferedReader b=new BufferedReader(new InputStreamReader(System.in));
int z=0,y=0,p=0,j=0,i=0,n=0,x=0,k=0;
String s;
n=Integer.parseInt(b.readLine());
s=b.readLine();
StringTokenizer c=new StringTokenizer(s);
for(i=0;i<n;i++)
{
s=c.nextToken();
p=s.length();
for(j=0;j<p;j++)
k+=Integer.parseInt(s.substring(j,j+1));
if(k%3==0)
x++;
if(k%3==1)
y++;
if(k%3==2)
z++;
k=0;
}
System.out.print(x/2+(int)Math.min(y,z));
}
}


import java.awt.Container;
import java.util.*;
public class Main {
    public static void main(String[] args){
        Scanner scan =new Scanner(System.in);
        int n1 =scan.nextInt();
        int[] count =new int[3];
        for (int i = 0; i < n1; i++) {
            int k1 =scan.nextInt();
            int sum = digitSum(k1)%3;
            count[sum]++;
        }
        int fin = 0;
        fin += count[0]/2;
        fin += Math.min(count[1], count[2]);
        System.out.println(fin);
    }
    public static int digitSum(int n1){
        int fin = 0;
        for (;n1!=0;){

            fin +=n1%10; n1/=10;
        }
        return fin;
    }
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long int;

const size_t max_string_length = 1000001;
template<class T> struct is_cstr: std::false_type {}; template<int N> struct is_cstr<char[N]> : std::true_type {};
template<typename T> constexpr string formcomm(const T& a) {if constexpr (is_same_v<T, int> || is_same_v<T, size_t>) return "%d"; else if constexpr (is_same_v<T, long long int>) return "%lld"; else if constexpr (is_same_v<T, short int>) return "%hd"; else if constexpr (is_same_v<T, unsigned int>) return "%u"; else if constexpr (is_same_v<T, unsigned long long int>) return "%llu"; else if constexpr (is_same_v<T, unsigned short int>) return "%hu"; else if constexpr (is_same_v<T, char>) return "%c"; else {printf("Type %s non prévu\n", typeid(a).name()); terminate();}}
template<typename T> constexpr string formout(const T& a) {if constexpr (is_same_v<T, float>) return "%.16f"; else if constexpr (is_same_v<T, double>) return "%.16lf"; else if constexpr (is_same_v<T, long double>) return "%.16Lf"; else if constexpr (is_same_v<T, string>) return "%s"; else if constexpr (is_cstr<T>::value) return "%s"; else return formcomm(a);}
template<typename T> const T& addout(const T& a) {return a;} const char* addout(const string& a) {return a.c_str();}
template<typename... Ts> void out(Ts&&... ts) {printf((formout(ts)+...).c_str(), addout(ts)...);}
template<typename It> void outs(It a, It b, string mid = " ", string fin = "\n") {if (a != b) {out(*a); ++a; for (; a != b; ++a) out (mid, *a);} out(fin);}
template<typename T> void outs(const T& l, string mid = " ", string fin = "\n") {outs(l.begin(), l.end(), mid, fin);}
template<typename T> constexpr string formin(const T& a) {if constexpr (is_same_v<T, float>) return "%f"; else if constexpr (is_same_v<T, double>) return "%lf"; else if constexpr (is_same_v<T, long double>) return "%Lf"; else if constexpr (is_same_v<T, string>) return "%s"; else if constexpr (is_cstr<T>::value) return "%s"; else return formcomm(a);}
template<typename T> constexpr int nstring(const T& a) {if constexpr (is_same_v<T, string>) return 1; else return 0;}
template<typename T> T* addin(T& a, char*& buf, string**& as) {return &a;} char* addin(string& a, char*& buf, string**& as) {char* ob = buf;buf+=max_string_length+1;*as = &a;++as;return ob;}
template<typename... Ts> void in(Ts&&... ts) {int ns=(nstring(ts)+...);string* as[max(ns,1)];char buf[1+(max_string_length+1)*ns];char* b=buf;string** c=as;
 scanf((formin(ts)+...).c_str(), addin(ts, b, c)...); while (c > as) {--c; b-=max_string_length+1; **c = string(b);}}
template<typename It> void ins(It a, It b) {for (; a != b; ++a) in (*a);} template<typename T> void ins(T& l) {ins(l.begin(), l.end());}
void inl(char* s) {scanf("%[^\n]", s);} void inl(string& s) {char buf[max_string_length+1]; inl(buf); s = string(buf);}

int main()
{
 const int INF = 1000000000;
 int n, m;
 in(n, m);
 vector<vector<int> > dep(n), isdep(n);
 vector<int> e(n);
 ins(e);
 for (int i = 0; i < m; ++i)
 {
  int u, v; in(u, v);
  dep[u].push_back(v);
  isdep[v].push_back(u);
 }
 vector<int> mintime(n, INF);
 vector<bool> istodo(n, false);
 deque<int> todo;
 for (int i = 0; i < n; ++i) if (dep[i].empty()) {todo.push_back(i); istodo[i] = true;}
 int mx = 0;
 while (!todo.empty())
 {
  int i = todo.front();
  todo.pop_front();
  istodo[i] = false;
  int mint = e[i]?1:0;
  for (auto j: dep[i])
  {
   int c = mintime[j];
   if (c == INF) {mint = INF; break;}
   if (e[i] && !e[j]) ++c;
   if (c > mint) mint = c;
  }
  if (mint != INF)
  {
   mintime[i] = mint;
   if (mint > mx) mx = mint;
   for (auto j: isdep[i]) if (!istodo[j]) {todo.push_back(j); istodo[j] = true;}
  }
 }
 out (mx, "\n");
 return 0;
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long int;

const size_t max_string_length = 1000001;
template<class T> struct is_cstr: std::false_type {}; template<int N> struct is_cstr<char[N]> : std::true_type {};
template<typename T> constexpr string formcomm(const T& a) {if constexpr (is_same_v<T, int> || is_same_v<T, size_t>) return "%d"; else if constexpr (is_same_v<T, long long int>) return "%lld"; else if constexpr (is_same_v<T, short int>) return "%hd"; else if constexpr (is_same_v<T, unsigned int>) return "%u"; else if constexpr (is_same_v<T, unsigned long long int>) return "%llu"; else if constexpr (is_same_v<T, unsigned short int>) return "%hu"; else if constexpr (is_same_v<T, char>) return "%c"; else {printf("Type %s non prévu\n", typeid(a).name()); terminate();}}
template<typename T> constexpr string formout(const T& a) {if constexpr (is_same_v<T, float>) return "%.16f"; else if constexpr (is_same_v<T, double>) return "%.16lf"; else if constexpr (is_same_v<T, long double>) return "%.16Lf"; else if constexpr (is_same_v<T, string>) return "%s"; else if constexpr (is_cstr<T>::value) return "%s"; else return formcomm(a);}
template<typename T> const T& addout(const T& a) {return a;} const char* addout(const string& a) {return a.c_str();}
template<typename... Ts> void out(Ts&&... ts) {printf((formout(ts)+...).c_str(), addout(ts)...);}
template<typename It> void outs(It a, It b, string mid = " ", string fin = "\n") {if (a != b) {out(*a); ++a; for (; a != b; ++a) out (mid, *a);} out(fin);}
template<typename T> void outs(const T& l, string mid = " ", string fin = "\n") {outs(l.begin(), l.end(), mid, fin);}
template<typename T> constexpr string formin(const T& a) {if constexpr (is_same_v<T, float>) return "%f"; else if constexpr (is_same_v<T, double>) return "%lf"; else if constexpr (is_same_v<T, long double>) return "%Lf"; else if constexpr (is_same_v<T, string>) return "%s"; else if constexpr (is_cstr<T>::value) return "%s"; else return formcomm(a);}
template<typename T> constexpr int nstring(const T& a) {if constexpr (is_same_v<T, string>) return 1; else return 0;}
template<typename T> T* addin(T& a, char*& buf, string**& as) {return &a;} char* addin(string& a, char*& buf, string**& as) {char* ob = buf;buf+=max_string_length+1;*as = &a;++as;return ob;}
template<typename... Ts> void in(Ts&&... ts) {int ns=(nstring(ts)+...);string* as[max(ns,1)];char buf[1+(max_string_length+1)*ns];char* b=buf;string** c=as;
 scanf((formin(ts)+...).c_str(), addin(ts, b, c)...); while (c > as) {--c; b-=max_string_length+1; **c = string(b);}}
template<typename It> void ins(It a, It b) {for (; a != b; ++a) in (*a);} template<typename T> void ins(T& l) {ins(l.begin(), l.end());}
void inl(char* s) {scanf("%[^\n]", s);} void inl(string& s) {char buf[max_string_length+1]; inl(buf); s = string(buf);}

int main()
{
 const int INF = 1000000000;
 int n, m;
 in(n, m);
 vector<vector<int> > dep(n), isdep(n);
 vector<int> e(n);
 ins(e);
 for (int i = 0; i < m; ++i)
 {
  int u, v; in(u, v);
  dep[u].push_back(v);
  isdep[v].push_back(u);
 }
 vector<int> mintime(n, INF);
 deque<int> todo;
 for (int i = 0; i < n; ++i) if (dep[i].empty()) todo.push_back(i);
 int mx = 0;
 while (!todo.empty())
 {
  int i = todo.front();
  todo.pop_front();
  int mint = e[i]?1:0;
  for (auto j: dep[i])
  {
   int c = mintime[j];
   if (c == INF) {mint = INF; break;}
   if (e[i] && !e[j]) ++c;
   if (c > mint) mint = c;
  }
  if (mint != INF)
  {
   mintime[i] = mint;
   if (mint > mx) mx = mint;
   for (auto j: isdep[i]) todo.push_back(j);
  }
 }
 out (mx, "\n");
 return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

const int maxn = 100010;
int n,m,a[maxn],ans,du[maxn],head[maxn],nextt[maxn],to[maxn],tot = 1;

void add(int x,int y)
{
    to[tot] = y;
    nextt[tot] = head[x];
    head[x] = tot++;
}

void solve()
{
    queue <int> q0,q1;
    for (int i = 1; i <= n; i++)
        if (!du[i])
        {
            if (!a[i])
                q0.push(i);
            else
                q1.push(i);
        }
    ans = 0;
    while (!q0.empty() || !q1.empty())
    {
        while (!q0.empty())
        {
            int u = q0.front();
            q0.pop();
            for (int i = head[u];i;i = nextt[i])
            {
                int v = to[i];
                if (--du[v] == 0)
                {
                    if (!a[v])
                        q0.push(v);
                    else
                        q1.push(v);
                }
            }
        }
        if (!q1.empty())
            ans++;
        while (!q1.empty())
        {
            int u = q1.front();
            q1.pop();
            for (int i = head[u];i;i = nextt[i])
            {
                int v = to[i];
                if (--du[v] == 0)
                {
                    if (a[v])
                        q1.push(v);
                    else
                        q0.push(v);
                }
            }
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i = 1; i <= n; i++)
        scanf("%d",&a[i]);
    for (int i = 1; i <= m; i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        x++;
        y++;
        add(y,x);
        du[x]++;
    }
    solve();
    printf("%d\n",ans);

    return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

const int maxn = 100010;
int n,m,a[maxn],ans,du[maxn],head[maxn],nextt[maxn],to[maxn],tot = 1;

void add(int x,int y)
{
    to[tot] = y;
    nextt[tot] = head[x];
    head[x] = tot++;
}

void solve()
{
    queue <int> q0,q1;
    for (int i = 1; i <= n; i++)
        if (!du[i])
        {
            if (!a[i])
                q0.push(i);
            else
                q1.push(i);
        }
    while (!q0.empty() || !q1.empty())
    {
        while (!q0.empty())
        {
            int u = q0.front();
            q0.pop();
            for (int i = head[u];i;i = nextt[i])
            {
                int v = to[i];
                if (--du[v] == 0)
                {
                    if (!a[v])
                        q0.push(v);
                    else
                        q1.push(v);
                }
            }
        }
        while (!q1.empty())
        {
            int u = q1.front();
            q1.pop();
            for (int i = head[u];i;i = nextt[i])
            {
                int v = to[i];
                if (a[v])
                    ans--;
                if (--du[v] == 0)
                {
                    if (a[v])
                        q1.push(v);
                    else
                        q0.push(v);
                }
            }
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d",&a[i]);
        if (a[i])
            ans++;
    }
    for (int i = 1; i <= m; i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        x++;
        y++;
        add(y,x);
        du[x]++;
    }
    solve();
    printf("%d\n",ans);

    return 0;
}


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

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

using ll = long long;

const ll mod = 1e9+7;
const int maxn = 1e6 + 5;

int n, m;
int type[maxn];
vector<int> rg[maxn];

int dp[maxn];

int solve(int at) {
    if (~dp[at]) return dp[at];
    dp[at]=type[at];
    for (int to: rg[at]) {
	int cost = (type[at]==1 && type[to]==0);
	dp[at]=max(dp[at],solve(to)+cost);
    }

    return dp[at];
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

    memset(dp,-1,sizeof(dp));

    cin>>n>>m;
    for (int i=0; i<n; i++) {
	cin>>type[i];
	// 0: main 1: co-op
    }
    for (int i=0; i<m; i++) {
	int u,v; cin>>u>>v;
	rg[u].push_back(v);
    }

    int ans = 0;
    for (int i=0; i<n; i++) {
	if (dp[i]==-1) {
	    ans = max(ans, solve(i));
	}
    }

    cout<<ans<<endl;
    return 0;
}


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

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

using ll = long long;

const ll mod = 1e9+7;
const int maxn = 1e6 + 5;

int n, m;
int type[maxn];
vector<int> g[maxn];
int indeg[maxn];

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

    cin>>n>>m;
    for (int i=0; i<n; i++) {
	cin>>type[i];
	type[i]^=1;
    }
    // 0: co, 1: main

    for (int i=0; i<m; i++) {
	int u,v; cin>>u>>v;
	g[v].push_back(u);
	indeg[u]++;
    }

    int co = 0;

    set<pair<int,int>> st;
    for (int i=0; i<n; i++) {
	if (indeg[i]==0) {
	    st.insert({type[i], i});
	}
    }

    int ans = 0;

    while (st.size()) {
	auto cur = *st.begin();
	int at = cur.second;
	st.erase(st.begin());
	if (cur.first == 0) {
	    co++;
	} else {
	    if (co>0) {
		ans++;
		co=0;
	    }
	}
	for (int to: g[at]) {
	    if (--indeg[to] == 0) {
		st.insert({type[to], to});
	    }
	}
    }

    if (co>0) ans++;

    cout<<ans<<endl;
    return 0;
}


#include<bits/stdc++.h>

#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define forn(i,o,n) for(int i=o;i<n;i++)
#define int long long
#define endl "\n"
#define mod 1000000007
#define mod2 998244353
#define double long double
#define pb push_back
#define mk make_pair
#define swap(x,y) (x^=y^=x^=y)
#define TT int ttt;cin>>ttt;while(ttt--)
#define oo 2000000000000000000

using namespace std;

int gcd(int a, int b){
    if (b == 0)
        return a;
    return gcd(b, a % b);
}
bool isPrime(int n){
    if(n < 2)
        return 0;
    if(n < 4)
        return 1;
    if(n % 2 == 0 or n % 3 == 0)
        return 0;
    for(int i = 5; i*i <= n; i += 6)
        if(n % i == 0 or n % (i+2) == 0)
            return 0;
    return 1;
}
int modexpo(int x,int p){
    int res = 1;
    x = x%mod;
    while(p){
        if(p%2)
            res = res * x;
        p >>= 1;
        x = x*x % mod;
        res %= mod;
    }
    return res;
}

int max(int a,int b){
    if(a>b){
        return a;
    }
    return b;
}

int min(int a,int b){
    if(a<b){
        return a;
    }
    return b;
}
const int N = 200005;
vector<int>g[N];
int type[N];
int deg[N];
int vis[N];
int complete[N];
int ans = 0;
set<int>co,ma,next_co,next_ma;
int32_t main(){
    IOS
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>type[i];
	}
	for(int i=0;i<m;i++){
		int a,b;
		cin>>a>>b;
		g[b].pb(a);
		deg[a]++;
	}
	for(int i=0;i<n;i++){
		if(deg[i]==0 && type[i]==0){
			next_ma.insert(i);
			vis[i]=1;
		}
		else if(deg[i]==0 && type[i]==1){
			next_co.insert(i);
			vis[i]=1;
		}
	}
	/*cout<<"g:"<<endl;
	for(int i=0;i<n;i++){
		cout<<i<<" : ";
		for(int j=0;j<g[i].size();j++){
			cout<<g[i][j]<<" ";
		}
		cout<<endl;
	}*/
	int flag = 0;
	while(next_co.size()>0 || next_ma.size()>0 || co.size()>0 || ma.size()>0){
		co = next_co;
		ma = next_ma;
		next_co.clear();
		next_ma.clear();
		//cout<<"co size "<<co.size()<<endl;
		//cout<<"ma size "<<ma.size()<<endl;
		queue<int>c,mn;
		for(auto x:ma){
			mn.push(x);
		}
		for(auto x:co){
			c.push(x);
		}
		while(mn.size()>0){
			int temp = mn.front();
			mn.pop();
			for(int i=0;i<g[temp].size();i++){
				if(complete[g[temp][i]]<deg[g[temp][i]]){
					complete[g[temp][i]]++;
					if(complete[g[temp][i]]==deg[g[temp][i]]){
						if(next_ma.find(g[temp][i])!=next_ma.end()){
							next_ma.erase(g[temp][i]);
						}
						vis[g[temp][i]]=1;
						if(type[g[temp][i]]==0){
							mn.push(g[temp][i]);
						}
						else{
							co.insert(g[temp][i]);
						}
					}
					else{
						next_ma.insert(g[temp][i]);
					}
				}
			}
		}
		if(co.size()>0){
			ans++;
		}
		while(c.size()>0){
			int temp = c.front();
			c.pop();
			for(int i=0;i<g[temp].size();i++){
				if(complete[g[temp][i]]<deg[g[temp][i]]){
					complete[g[temp][i]]++;
					if(complete[g[temp][i]]==deg[g[temp][i]]){
						if(next_co.find(g[temp][i])!=next_co.end()){
							next_co.erase(g[temp][i]);
						}
						vis[g[temp][i]]=1;
						if(type[g[temp][i]]==1){
							c.push(g[temp][i]);
						}
						else{
							next_ma.insert(g[temp][i]);
						}
					}
					else{
						next_co.insert(g[temp][i]);
					}
				}
			}
		}
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>

#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define forn(i,o,n) for(int i=o;i<n;i++)
#define int long long
#define endl "\n"
#define mod 1000000007
#define mod2 998244353
#define double long double
#define pb push_back
#define mk make_pair
#define swap(x,y) (x^=y^=x^=y)
#define TT int ttt;cin>>ttt;while(ttt--)
#define oo 2000000000000000000

using namespace std;

int gcd(int a, int b){
    if (b == 0)
        return a;
    return gcd(b, a % b);
}
bool isPrime(int n){
    if(n < 2)
        return 0;
    if(n < 4)
        return 1;
    if(n % 2 == 0 or n % 3 == 0)
        return 0;
    for(int i = 5; i*i <= n; i += 6)
        if(n % i == 0 or n % (i+2) == 0)
            return 0;
    return 1;
}
int modexpo(int x,int p){
    int res = 1;
    x = x%mod;
    while(p){
        if(p%2)
            res = res * x;
        p >>= 1;
        x = x*x % mod;
        res %= mod;
    }
    return res;
}

int max(int a,int b){
    if(a>b){
        return a;
    }
    return b;
}

int min(int a,int b){
    if(a<b){
        return a;
    }
    return b;
}
const int N = 200005;
vector<int>g[N];
int type[N];
int deg[N];
int vis[N];
int complete[N];
int ans = 0;
set<int>co,ma,next_co,next_ma;

void bfs_main(int u){
	for(int i=0;i<g[u].size();i++){
		if(complete[g[u][i]]<deg[g[u][i]]){
			complete[g[u][i]]++;
			if(complete[g[u][i]]==deg[g[u][i]]){
				if(type[g[u][i]]==0){
					bfs_main(g[u][i]);
				}
				else{
					co.insert(g[u][i]);
				}
			}
		}
	}
}

void bfs_co(int u){
	for(int i=0;i<g[u].size();i++){
		if(complete[g[u][i]]<deg[g[u][i]]){
			complete[g[u][i]]++;
			if(complete[g[u][i]]==deg[g[u][i]]){
				if(type[g[u][i]]==1){
					bfs_co(g[u][i]);
				}
				else{
					ma.insert(g[u][i]);
				}
			}
		}
	}
}
int32_t main(){
    IOS
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>type[i];
	}
	for(int i=0;i<m;i++){
		int a,b;
		cin>>a>>b;
		g[b].pb(a);
		deg[a]++;
	}
	for(int i=0;i<n;i++){
		if(deg[i]==0 && type[i]==0){
			ma.insert(i);
		}
		else if(deg[i]==0){
			co.insert(i);
		}
	}
	while(ma.size()>0 || co.size()>0){
		for(auto x:ma){
			bfs_main(x);
		}
		ma.clear();
		if(co.size()>0){
			ans++;
		}
		for(auto x:co){
			bfs_co(x);
		}
		co.clear();
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>

#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define forn(i,o,n) for(int i=o;i<n;i++)
#define int long long
#define endl "\n"
#define mod 1000000007
#define mod2 998244353
#define double long double
#define pb push_back
#define mk make_pair
#define swap(x,y) (x^=y^=x^=y)
#define TT int ttt;cin>>ttt;while(ttt--)
#define oo 2000000000000000000

using namespace std;

int gcd(int a, int b){
    if (b == 0)
        return a;
    return gcd(b, a % b);
}
bool isPrime(int n){
    if(n < 2)
        return 0;
    if(n < 4)
        return 1;
    if(n % 2 == 0 or n % 3 == 0)
        return 0;
    for(int i = 5; i*i <= n; i += 6)
        if(n % i == 0 or n % (i+2) == 0)
            return 0;
    return 1;
}
int modexpo(int x,int p){
    int res = 1;
    x = x%mod;
    while(p){
        if(p%2)
            res = res * x;
        p >>= 1;
        x = x*x % mod;
        res %= mod;
    }
    return res;
}

int max(int a,int b){
    if(a>b){
        return a;
    }
    return b;
}

int min(int a,int b){
    if(a<b){
        return a;
    }
    return b;
}
const int N = 200005;
vector<int>g[N];
int type[N];
int deg[N];
int vis[N];
int complete[N];
int ans = 0;
set<int>co,ma,next_co,next_ma;
int32_t main(){
    IOS
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>type[i];
	}
	for(int i=0;i<m;i++){
		int a,b;
		cin>>a>>b;
		g[b].pb(a);
		deg[a]++;
	}
	for(int i=0;i<n;i++){
		if(deg[i]==0 && type[i]==0){
			next_ma.insert(i);
			vis[i]=1;
		}
		else if(deg[i]==0 && type[i]==1){
			next_co.insert(i);
			vis[i]=1;
		}
	}
	/*cout<<"g:"<<endl;
	for(int i=0;i<n;i++){
		cout<<i<<" : ";
		for(int j=0;j<g[i].size();j++){
			cout<<g[i][j]<<" ";
		}
		cout<<endl;
	}*/
	int flag = 0;
	while(next_co.size()>0 || next_ma.size()>0 || co.size()>0 || ma.size()>0){
		co = next_co;
		ma = next_ma;
		next_co.clear();
		next_ma.clear();
		//cout<<"co size "<<co.size()<<endl;
		//cout<<"ma size "<<ma.size()<<endl;
		queue<int>c,mn;
		for(auto x:ma){
			mn.push(x);
		}
		for(auto x:co){
			c.push(x);
		}
		while(mn.size()>0){
			int temp = mn.front();
			mn.pop();
			for(int i=0;i<g[temp].size();i++){
				if(complete[g[temp][i]]<deg[g[temp][i]]){
					complete[g[temp][i]]++;
					if(complete[g[temp][i]]==deg[g[temp][i]]){
						vis[g[temp][i]]=1;
						if(type[g[temp][i]]==0){
							mn.push(g[temp][i]);
						}
						else{
							co.insert(g[temp][i]);
						}
					}
					else{
						next_ma.insert(g[temp][i]);
					}
				}
			}
		}
		if(co.size()>0){
			ans++;
		}
		while(c.size()>0){
			int temp = c.front();
			c.pop();
			for(int i=0;i<g[temp].size();i++){
				if(complete[g[temp][i]]<deg[g[temp][i]]){
					complete[g[temp][i]]++;
					if(complete[g[temp][i]]==deg[g[temp][i]]){
						if(next_co.find(g[temp][i])!=next_co.end()){
							next_co.erase(g[temp][i]);
						}
						vis[g[temp][i]]=1;
						if(type[g[temp][i]]==1){
							c.push(g[temp][i]);
						}
						else{
							next_ma.insert(g[temp][i]);
						}
					}
					else{
						next_co.insert(g[temp][i]);
					}
				}
			}
		}
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>

#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define forn(i,o,n) for(int i=o;i<n;i++)
#define int long long
#define endl "\n"
#define mod 1000000007
#define mod2 998244353
#define double long double
#define pb push_back
#define mk make_pair
#define swap(x,y) (x^=y^=x^=y)
#define TT int ttt;cin>>ttt;while(ttt--)
#define oo 2000000000000000000

using namespace std;

int gcd(int a, int b){
    if (b == 0)
        return a;
    return gcd(b, a % b);
}
bool isPrime(int n){
    if(n < 2)
        return 0;
    if(n < 4)
        return 1;
    if(n % 2 == 0 or n % 3 == 0)
        return 0;
    for(int i = 5; i*i <= n; i += 6)
        if(n % i == 0 or n % (i+2) == 0)
            return 0;
    return 1;
}
int modexpo(int x,int p){
    int res = 1;
    x = x%mod;
    while(p){
        if(p%2)
            res = res * x;
        p >>= 1;
        x = x*x % mod;
        res %= mod;
    }
    return res;
}

int max(int a,int b){
    if(a>b){
        return a;
    }
    return b;
}

int min(int a,int b){
    if(a<b){
        return a;
    }
    return b;
}
const int N = 200005;
vector<int>g[N];
int type[N];
int deg[N];
int vis[N];
int complete[N];
int ans = 0;
set<int>co,ma,next_co,next_ma;
int32_t main(){
    IOS
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>type[i];
	}
	for(int i=0;i<m;i++){
		int a,b;
		cin>>a>>b;
		g[b].pb(a);
		deg[a]++;
	}
	for(int i=0;i<n;i++){
		if(deg[i]==0 && type[i]==0){
			next_ma.insert(i);
			vis[i]=1;
		}
		else if(deg[i]==0 && type[i]==1){
			next_co.insert(i);
			vis[i]=1;
		}
	}
	/*cout<<"g:"<<endl;
	for(int i=0;i<n;i++){
		cout<<i<<" : ";
		for(int j=0;j<g[i].size();j++){
			cout<<g[i][j]<<" ";
		}
		cout<<endl;
	}*/
	int flag = 0;
	while(next_co.size()>0 || next_ma.size()>0 || co.size()>0 || ma.size()>0){
		co = next_co;
		ma = next_ma;
		next_co.clear();
		next_ma.clear();
		/*cout<<"ma : "<<endl;
		for(auto x:ma){
			cout<<x<<" ";
		}
		cout<<endl;
		cout<<"co : "<<endl;
		for(auto x:co){
			cout<<x<<" ";
		}
		cout<<endl;*/
		if(ma.size()>0){
			flag=0;
		}
		for(auto x:ma){
			for(int i=0;i<g[x].size();i++){
				if(complete[g[x][i]] < deg[g[x][i]]){
					complete[g[x][i]]++;
					if(complete[g[x][i]]==deg[g[x][i]] && vis[g[x][i]]==0){
						vis[g[x][i]]=1;
						if(type[g[x][i]]==0){
							next_ma.insert(g[x][i]);
						}
						else{
							next_co.insert(g[x][i]);
						}
					}
				}
			}
		}
		if(co.size()>0 && flag == 0){
			ans++;
			flag=1;
		}
		for(auto x:co){
			for(int i=0;i<g[x].size();i++){
				if(complete[g[x][i]] < deg[g[x][i]]){
					complete[g[x][i]]++;
					if(complete[g[x][i]]==deg[g[x][i]] && vis[g[x][i]]==0){
						vis[g[x][i]]=1;
						if(type[g[x][i]]==0){
							next_ma.insert(g[x][i]);
						}
						else{
							next_co.insert(g[x][i]);
						}
					}
				}
			}
		}
	}
	cout<<ans<<endl;
}


//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define ll long long int
#define ld long double
#define pb push_back
#define mp make_pair
#define mod 1000000007
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);
#define all(x) x.begin(),x.end()
#define F first
#define S second
#define fo(i,n) for(int i=0;i<(n);i++)
#define inp(a) int a;cin>>a;
#define inpa(a,n)vector<int> a(n);fo(i,n)cin>>a[i];
#define printclock cerr<<"Time : "<<1000*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
using namespace std;
#define int ll
// #define MAX 20
#define INF (int)1e18

template<class T> ostream& operator<<(ostream& cout,deque<T> V)
{cout<<"[ ";for(auto v:V)cout<<v<<' ';return cout<<']';}
template<class L,class R> ostream& operator<<(ostream& cout,pair<L, R> P)
{return cout<<'('<<P.F<<','<< P.S<<')';}

int n,m;
deque<int> curr1,curr2;
vector<int> done,col;
vector<vector<int>> conn;

signed main()
{
	fio
	cin>>n>>m;
	done.resize(n);
	col.resize(n);
	conn.resize(n);
	fo(i,n)
		cin>>col[i];
	vector<int> count(n);
	fo(i,m)
	{
		inp(x) inp(y)
		count[x]++;
		conn[y].pb(x);
	}
	fo(i,n)
	{
		if(count[i]==0)
		{
			if(!col[i])
			{
				done[i]=1;
				curr1.pb(i);
			}
			else
			{
				done[i]=1;
				curr2.pb(i);
			}
		}
	}
	int ans=0;
	bool turn=0;
	while(curr1.size() || curr2.size())
	{
		if(turn%2==0)
		{
			// cerr<<"curr1: "<<curr1<<'\n';
			while(curr1.size())
			{
				for(int i:conn[curr1[0]])
				{
					if(!done[i])
					{
						if(!col[i])
						{
							done[i]=1;
							curr1.pb(i);
						}
						else
						{
							done[i]=1;
							curr2.pb(i);
						}
					}
				}
				curr1.pop_front();
			}
		}
		else
		{
			// cerr<<"curr2: "<<curr2<<'\n';
			if(curr2.size())
				ans++;
			while(curr2.size())
			{
				for(int i:conn[curr2[0]])
				{
					if(!done[i])
					{
						if(!col[i])
						{
							done[i]=1;
							curr1.pb(i);
						}
						else
						{
							done[i]=1;
							curr2.pb(i);
						}
					}
				}
				curr2.pop_front();
			}
		}
		turn=1-turn;
	}
	cout<<ans<<'\n';
	printclock;
}


//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define ll long long int
#define ld long double
#define pb push_back
#define mp make_pair
#define mod 1000000007
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);
#define all(x) x.begin(),x.end()
#define F first
#define S second
#define fo(i,n) for(int i=0;i<(n);i++)
#define inp(a) int a;cin>>a;
#define inpa(a,n)vector<int> a(n);fo(i,n)cin>>a[i];
#define printclock cerr<<"Time : "<<1000*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
using namespace std;
#define int ll
// #define MAX 20
#define INF (int)1e18

template<class T> ostream& operator<<(ostream& cout,vector<T> V)
{cout<<"[ ";for(auto v:V)cout<<v<<' ';return cout<<']';}
template<class L,class R> ostream& operator<<(ostream& cout,pair<L, R> P)
{return cout<<'('<<P.F<<','<< P.S<<')';}

int n,m,root;
vector<vector<int>> conn;
vector<int> done,a,ans;

int dfs1(int node)
{
	if(done[node])
		return ans[node];
	done[node]=root+1;
	for(int i:conn[node])
	{
		if(done[root] && done[root]!=root+1)
			continue;
		ans[node]=max(ans[node],dfs1(i)+(a[node] && !a[i]));
	}
	return ans[node];
}

signed main()
{
	fio
	cin>>n>>m;
	a.resize(n+1);
	fo(i,n)
		cin>>a[i];
	conn.resize(n+1);
	vector<int> count(n);
	fo(i,m)
	{
		inp(x) inp(y)
		conn[x].pb(y);
		count[y]++;
	}
	int fans=0;
	ans.resize(n+1);
	done.resize(n+1);
	int root;
	fo(i,n)
	{
		if(!count[i])
		{
			conn[n].pb(i);
		}
	}

	// cerr<<ans<<endl;

	a[n]=1;
	cout<<dfs1(n)<<'\n';
	printclock;
}


//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define ll long long int
#define ld long double
#define pb push_back
#define mp make_pair
#define mod 1000000007
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);
#define all(x) x.begin(),x.end()
#define F first
#define S second
#define fo(i,n) for(int i=0;i<(n);i++)
#define inp(a) int a;cin>>a;
#define inpa(a,n)vector<int> a(n);fo(i,n)cin>>a[i];
#define printclock cerr<<"Time : "<<1000*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
using namespace std;
#define int ll
// #define MAX 20
#define INF (int)1e18

template<class T> ostream& operator<<(ostream& cout,vector<T> V)
{cout<<"[ ";for(auto v:V)cout<<v<<' ';return cout<<']';}
template<class L,class R> ostream& operator<<(ostream& cout,pair<L, R> P)
{return cout<<'('<<P.F<<','<< P.S<<')';}

int n,m,root;
vector<vector<int>> conn;
vector<int> done,a,ans;

int dfs1(int node)
{
	if(done[node])
		return ans[node];
	done[node]=root+1;
	for(int i:conn[node])
	{
		if(done[root] && done[root]!=root+1)
			continue;
		ans[node]=max(ans[node],dfs1(i)+(a[node] && !a[i]));
	}
	return ans[node];
}

signed main()
{
	fio
	cin>>n>>m;
	a.resize(n);
	fo(i,n)
		cin>>a[i];
	conn.resize(n);
	vector<int> count(n);
	fo(i,m)
	{
		inp(x) inp(y)
		conn[x].pb(y);
		count[y]++;
	}
	int fans=0;
	ans.resize(n);
	done.resize(n);
	int root;
	fo(i,n)
	{
		if(!count[i])
		{
			root=i;
			fans+=dfs1(i)+(!a[i]);
		}
	}

	cout<<fans<<'\n';
	printclock;
}


//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define ll long long int
#define ld long double
#define pb push_back
#define mp make_pair
#define mod 1000000007
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);
#define all(x) x.begin(),x.end()
#define F first
#define S second
#define fo(i,n) for(int i=0;i<(n);i++)
#define inp(a) int a;cin>>a;
#define inpa(a,n)vector<int> a(n);fo(i,n)cin>>a[i];
#define printclock cerr<<"Time : "<<1000*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
using namespace std;
#define int ll
// #define MAX 20
#define INF (int)1e18

template<class T> ostream& operator<<(ostream& cout,deque<T> V)
{cout<<"[ ";for(auto v:V)cout<<v<<' ';return cout<<']';}
template<class L,class R> ostream& operator<<(ostream& cout,pair<L, R> P)
{return cout<<'('<<P.F<<','<< P.S<<')';}

int n,m;
deque<int> curr1,curr2;
vector<int> col;
vector<vector<int>> conn;
vector<int> cc;

signed main()
{
	fio
	cin>>n>>m;
	col.resize(n);
	conn.resize(n);
	cc.resize(n);
	fo(i,n)
		cin>>col[i];
	vector<int> count(n);
	fo(i,m)
	{
		inp(x) inp(y)
		count[x]++;
		conn[y].pb(x);
	}
	fo(i,n)
	{
		if(count[i]==0)
		{
			if(!col[i])
			{
				curr1.pb(i);
			}
			else
			{
				curr2.pb(i);
			}
		}
	}
	int ans=0;
	bool turn=0;
	while(curr1.size() || curr2.size())
	{
		if(turn%2==0)
		{
			while(curr1.size())
			{
				for(int i:conn[curr1[0]])
				{
					cc[i]++;
					if(cc[i]==count[i])
					{
						if(!col[i])
						{
							curr1.pb(i);
						}
						else
						{
							curr2.pb(i);
						}
					}
				}
				curr1.pop_front();
			}
		}
		else
		{
			if(curr2.size())
				ans++;
			while(curr2.size())
			{
				for(int i:conn[curr2[0]])
				{
					cc[i]++;
					if(cc[i]==count[i])
					{
						if(!col[i])
						{
							curr1.pb(i);
						}
						else
						{
							curr2.pb(i);
						}
					}
				}
				curr2.pop_front();
			}
		}
		turn=1-turn;
	}
	cout<<ans<<'\n';
	printclock;
}


//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define ll long long int
#define ld long double
#define pb push_back
#define mp make_pair
#define mod 1000000007
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);
#define all(x) x.begin(),x.end()
#define F first
#define S second
#define fo(i,n) for(int i=0;i<(n);i++)
#define inp(a) int a;cin>>a;
#define inpa(a,n)vector<int> a(n);fo(i,n)cin>>a[i];
#define printclock cerr<<"Time : "<<1000*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
using namespace std;
#define int ll
// #define MAX 20
#define INF (int)1e18

template<class T> ostream& operator<<(ostream& cout,vector<T> V)
{cout<<"[ ";for(auto v:V)cout<<v<<' ';return cout<<']';}
template<class L,class R> ostream& operator<<(ostream& cout,pair<L, R> P)
{return cout<<'('<<P.F<<','<< P.S<<')';}

int n,m;
vector<vector<int>> conn;
vector<int> done,a,ans;

int dfs1(int node)
{
	if(done[node])
		return ans[node];
	done[node]=1;
	for(int i:conn[node])
	{
		ans[node]=max(ans[node],dfs1(i)+(a[node] && !a[i]));
	}
	return ans[node];
}

signed main()
{
	fio
	cin>>n>>m;
	a.resize(n);
	fo(i,n)
		cin>>a[i];
	conn.resize(n);
	vector<int> count(n);
	fo(i,m)
	{
		inp(x) inp(y)
		conn[x].pb(y);
		count[y]++;
	}
	int fans=0;
	ans.resize(n);
	done.resize(n);
	int root;
	fo(i,n)
	{
		if(!count[i])
		{
			fans+=dfs1(i)+(!a[i]);
		}
	}

	cout<<fans<<'\n';
	printclock;
}


//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define ll long long int
#define ld long double
#define pb push_back
#define mp make_pair
#define mod 1000000007
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);
#define all(x) x.begin(),x.end()
#define F first
#define S second
#define fo(i,n) for(int i=0;i<(n);i++)
#define inp(a) int a;cin>>a;
#define inpa(a,n)vector<int> a(n);fo(i,n)cin>>a[i];
#define printclock cerr<<"Time : "<<1000*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
using namespace std;
#define int ll
// #define MAX 20
#define INF (int)1e18

template<class T> ostream& operator<<(ostream& cout,vector<T> V)
{cout<<"[ ";for(auto v:V)cout<<v<<' ';return cout<<']';}
template<class L,class R> ostream& operator<<(ostream& cout,pair<L, R> P)
{return cout<<'('<<P.F<<','<< P.S<<')';}

int n,m;
vector<vector<int>> conn;
vector<int> done,a,ans;

int dfs1(int node)
{
	if(done[node])
		return ans[node];
	done[node]=1;
	for(int i:conn[node])
	{
		ans[node]=max(ans[node],dfs1(i)+(a[node] && !a[i]));
	}
	return ans[node];
}

signed main()
{
	fio
	cin>>n>>m;
	a.resize(n+1);
	fo(i,n)
		cin>>a[i];
	conn.resize(n+1);
	vector<int> count(n);
	fo(i,m)
	{
		inp(x) inp(y)
		conn[x].pb(y);
		count[y]++;
	}
	int fans=0;
	ans.resize(n+1);
	done.resize(n+1);
	fo(i,n)
	{
		if(!count[i])
		{
			conn[n].pb(i);
		}
	}

	// cerr<<ans<<endl;

	a[n]=1;
	cout<<dfs1(n)<<'\n';s
	printclock;
}


//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define ll long long int
#define ld long double
#define pb push_back
#define mp make_pair
#define mod 1000000007
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);
#define all(x) x.begin(),x.end()
#define F first
#define S second
#define fo(i,n) for(int i=0;i<(n);i++)
#define inp(a) int a;cin>>a;
#define inpa(a,n)vector<int> a(n);fo(i,n)cin>>a[i];
#define printclock cerr<<"Time : "<<1000*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
using namespace std;
#define int ll
// #define MAX 20
#define INF (int)1e18

template<class T> ostream& operator<<(ostream& cout,vector<T> V)
{cout<<"[ ";for(auto v:V)cout<<v<<' ';return cout<<']';}
template<class L,class R> ostream& operator<<(ostream& cout,pair<L, R> P)
{return cout<<'('<<P.F<<','<< P.S<<')';}

int n,m;
vector<vector<int>> conn;
vector<int> done,a,ans;

int dfs1(int node)
{
	if(done[node])
		return ans[node];
	done[node]=1;
	for(int i:conn[node])
	{
		ans[node]+=dfs1(i)+(a[node] && !a[i]);
	}
	return ans[node];
}

signed main()
{
	fio
	cin>>n>>m;
	a.resize(n);
	fo(i,n)
		cin>>a[i];
	conn.resize(n);
	vector<int> count(n);
	fo(i,m)
	{
		inp(x) inp(y)
		conn[x].pb(y);
		count[y]++;
	}
	int root;
	fo(i,n)
		if(!count[i])
			root=i;
	ans.resize(n);
	done.resize(n);
	cout<<dfs1(root)+(!a[root])<<'\n';
	printclock;
}


//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define ll long long int
#define ld long double
#define pb push_back
#define mp make_pair
#define mod 1000000007
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);
#define all(x) x.begin(),x.end()
#define F first
#define S second
#define fo(i,n) for(int i=0;i<(n);i++)
#define inp(a) int a;cin>>a;
#define inpa(a,n)vector<int> a(n);fo(i,n)cin>>a[i];
#define printclock cerr<<"Time : "<<1000*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
using namespace std;
#define int ll
// #define MAX 20
#define INF (int)1e18

template<class T> ostream& operator<<(ostream& cout,vector<T> V)
{cout<<"[ ";for(auto v:V)cout<<v<<' ';return cout<<']';}
template<class L,class R> ostream& operator<<(ostream& cout,pair<L, R> P)
{return cout<<'('<<P.F<<','<< P.S<<')';}

int n,m;
vector<vector<int>> conn;
vector<int> done,a,ans;

int dfs1(int node)
{
	if(done[node])
		return ans[node];
	done[node]=1;
	for(int i:conn[node])
	{
		ans[node]=max(ans[node],dfs1(i)+(a[node] && !a[i]));
	}
	return ans[node];
}

signed main()
{
	fio
	cin>>n>>m;
	a.resize(n);
	fo(i,n)
		cin>>a[i];
	conn.resize(n);
	vector<int> count(n);
	fo(i,m)
	{
		inp(x) inp(y)
		conn[x].pb(y);
		count[y]++;
	}
	int root;
	fo(i,n)
		if(!count[i])
			root=i;
	ans.resize(n);
	done.resize(n);
	cout<<dfs1(root)+(!a[root])<<'\n';
	printclock;
}


//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define ll long long int
#define ld long double
#define pb push_back
#define mp make_pair
#define mod 1000000007
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);
#define all(x) x.begin(),x.end()
#define F first
#define S second
#define fo(i,n) for(int i=0;i<(n);i++)
#define inp(a) int a;cin>>a;
#define inpa(a,n)vector<int> a(n);fo(i,n)cin>>a[i];
#define printclock cerr<<"Time : "<<1000*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
using namespace std;
#define int ll
// #define MAX 20
#define INF (int)1e18

template<class T> ostream& operator<<(ostream& cout,vector<T> V)
{cout<<"[ ";for(auto v:V)cout<<v<<' ';return cout<<']';}
template<class L,class R> ostream& operator<<(ostream& cout,pair<L, R> P)
{return cout<<'('<<P.F<<','<< P.S<<')';}

int n,m;
vector<vector<int>> conn;
vector<int> done,a,ans;

int dfs1(int node)
{
	if(done[node])
		return ans[node];
	done[node]=1;
	for(int i:conn[node])
	{
		ans[node]=max(ans[node],dfs1(i)+(a[node] && !a[i]));
	}
	return ans[node];
}

signed main()
{
	fio
	cin>>n>>m;
	a.resize(n+1);
	fo(i,n)
		cin>>a[i];
	conn.resize(n+1);
	vector<int> count(n);
	fo(i,m)
	{
		inp(x) inp(y)
		conn[x].pb(y);
		count[y]++;
	}
	int fans=0;
	ans.resize(n+1);
	done.resize(n+1);
	fo(i,n)
	{
		if(!count[i])
		{
			conn[n].pb(i);
		}
	}

	// cerr<<ans<<endl;

	a[n]=1;
	cout<<dfs1(n)<<'\n';
	printclock;
}


//#define _GLIBCXX_DEBUG

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

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T1, typename T2>
bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>
bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>
void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}
template<typename T>
void debug(vector<vector<T>>&v,ll h,ll w){for(ll i=0;i<h;i++)
{cout<<v[i][0];for(ll j=1;j<w;j++)cout spa v[i][j];cout<<endl;}};
void debug(vector<string>&v,ll h,ll w){for(ll i=0;i<h;i++)
{for(ll j=0;j<w;j++)cout<<v[i][j];cout<<endl;}};
template<typename T>
void debug(vector<T>&v,ll n){if(n!=0)cout<<v[0];
for(ll i=1;i<n;i++)cout spa v[i];cout<<endl;};
template<typename T>
vector<vector<T>>vec(ll x, ll y, T w){
  vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
vector<ll>dx={1,-1,0,0,1,1,-1,-1};
vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>
vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>
auto make_v(size_t a,Ts... ts){
  return vector<decltype(make_v(ts...))>(a,make_v(ts...));
}
template<typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2>&p){
  return os << p.first << " " << p.second;
}
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());

int main(){
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  ll res=0,buf=0;
  bool judge = true;
  ll n,m;cin>>n>>m;
  vector<ll>e(n);
  rep(i,0,n)cin>>e[i];
  vector<ll>d(n);
  vector<vector<ll>>g(n);
  rep(i,0,m){
    ll u,v;cin>>u>>v;
    g[v].PB(u);
    d[u]++;
  }
  vector<queue<ll>>que(2);
  auto del=[&](ll x){
    for(auto to:g[x]){
      d[to]--;
      if(d[to]==0)que[e[to]].push(to);
    }
  };
  rep(i,0,n)if(d[i]==0)que[e[i]].push(i);
  while(!que[0].empty()||!que[1].empty()){
    while(!que[0].empty()){
      del(que[0].front());
      que[0].pop();
    }
    if(que[1].empty())break;
    res++;
    while(!que[1].empty()){
      del(que[1].front());
      que[1].pop();
    }
  }
  cout<<res<<endl;
  return 0;
}


#ifdef APTEST
#include "debug_tools/program.h"
#endif
#include <algorithm>
#include <iostream>
#include <iterator>
#include <queue>
using namespace std;
const unsigned int maxn = 1e5, maxm = 1e5;

struct edge
{
    unsigned int to;
    const edge* pre;
} ed[maxm + 1];
const edge* head[maxn + 1];
unsigned int degree[maxn + 1];
bool co[maxn + 1];
queue<unsigned int> mq, cq;

void addEdge(const unsigned int from, const unsigned int to)
{
    static edge* cur = ed;
    cur->to = to;
    cur->pre = head[from];
    head[from] = cur;
    ++cur;
    ++degree[to];
}
inline void add(const unsigned int i)
{
    if (!degree[i])
        (co[i] ? &cq : &mq)->push(i);
}
void redu(queue<unsigned int>& q)
{
    while (!q.empty())
    {
        const unsigned int c = q.front();
        q.pop();
        for (const edge* i = head[c]; i; i = i->pre)
        {
            const unsigned int to = i->to;
            --degree[to];
            add(to);
        }
    }
}
unsigned int topological(const unsigned int n)
{
    unsigned int ret = 0;
    for (unsigned int i = 1; i <= n; ++i)
        add(i);
    while (!mq.empty() || !cq.empty())
    {
        redu(mq);
        if (!cq.empty())
        {
            ++ret;
            redu(cq);
        }
    }
    return ret;
}
int main()
{
#ifndef APTEST
    ios_base::sync_with_stdio(false);
#endif
    unsigned int n, m;
    cin >> n >> m;
    copy_n(istream_iterator<unsigned int>(cin), n, co);
    for (unsigned int i = 0; i < m; ++i)
    {
        unsigned int t1, t2;
        cin >> t1 >> t2;
        addEdge(t2, t1);
    }
    cout << topological(n) << endl;
    return 0;
}


#ifdef APTEST
#include "debug_tools/program.h"
#endif
#include <algorithm>
#include <iostream>
#include <iterator>
#include <queue>
using namespace std;
const unsigned int maxn = 1e5, maxm = 1e5;

struct edge
{
    unsigned int to;
    const edge* pre;
} ed[maxm + 1];
const edge* head[maxn + 1];
unsigned int degree[maxn + 1];
bool co[maxn + 1];
queue<unsigned int> mq, cq;

void addEdge(const unsigned int from, const unsigned int to)
{
    static edge* cur = ed;
    cur->to = to;
    cur->pre = head[from];
    head[from] = cur;
    ++cur;
    ++degree[to];
}
inline void add(const unsigned int i)
{
    if (!degree[i])
        (co[i] ? &cq : &mq)->push(i);
}
void redu(queue<unsigned int>& q)
{
    while (!q.empty())
    {
        const unsigned int c = q.front();
        q.pop();
        for (const edge* i = head[c]; i; i = i->pre)
        {
            const unsigned int to = i->to;
            --degree[to];
            add(to);
        }
    }
}
unsigned int topological(const unsigned int n)
{
    unsigned int ret = 0;
    for (unsigned int i = 1; i <= n; ++i)
        add(i);
    const bool fl = mq.empty();
    while (!mq.empty() || !cq.empty())
    {
        redu(mq);
        if (!cq.empty())
        {
            ++ret;
            redu(cq);
        }
    }
    return ret - fl;
}
int main()
{
#ifndef APTEST
    ios_base::sync_with_stdio(false);
#endif
    unsigned int n, m;
    cin >> n >> m;
    copy_n(istream_iterator<unsigned int>(cin), n, co);
    for (unsigned int i = 0; i < m; ++i)
    {
        unsigned int t1, t2;
        cin >> t1 >> t2;
        addEdge(t2, t1);
    }
    cout << topological(n) << endl;
    return 0;
}


#ifdef APTEST
#include "debug_tools/program.h"
#endif
#include <algorithm>
#include <iostream>
#include <iterator>
#include <queue>
using namespace std;
const unsigned int maxn = 1e5, maxm = 1e5;

struct edge
{
    unsigned int to;
    const edge* pre;
} ed[maxm + 1];
const edge* head[maxn + 1];
unsigned int degree[maxn + 1];
bool co[maxn + 1];
queue<unsigned int> mq, cq;

void addEdge(const unsigned int from, const unsigned int to)
{
    static edge* cur = ed;
    cur->to = to;
    cur->pre = head[from];
    head[from] = cur;
    ++cur;
    ++degree[to];
}
inline void add(const unsigned int i)
{
    if (!degree[i])
        (co[i] ? &cq : &mq)->push(i);
}
void redu(queue<unsigned int>& q)
{
    while (!q.empty())
    {
        const unsigned int c = q.front();
        q.pop();
        for (const edge* i = head[c]; i; i = i->pre)
        {
            const unsigned int to = i->to;
            --degree[to];
            add(to);
        }
    }
}
unsigned int topological(const unsigned int n)
{
    unsigned int ret = 0;
    for (unsigned int i = 0; i < n; ++i)
        add(i);
    while (!mq.empty() || !cq.empty())
    {
        redu(mq);
        if (!cq.empty())
        {
            ++ret;
            redu(cq);
        }
    }
    return ret;
}
int main()
{
#ifndef APTEST
    ios_base::sync_with_stdio(false);
#endif
    unsigned int n, m;
    cin >> n >> m;
    copy_n(istream_iterator<unsigned int>(cin), n, co);
    for (unsigned int i = 0; i < m; ++i)
    {
        unsigned int t1, t2;
        cin >> t1 >> t2;
        addEdge(t2, t1);
    }
    cout << topological(n) << endl;
    return 0;
}


#ifdef APTEST
#include "debug_tools/program.h"
#endif
#include <iostream>
#include <queue>
using namespace std;
const unsigned int maxn = 1e5, maxm = 1e5;

struct edge
{
    unsigned int to;
    const edge* pre;
} ed[maxm + 1];
const edge* head[maxn + 1];
unsigned int degree[maxn + 1];
bool co[maxn + 1];
queue<unsigned int> mq, cq;

void addEdge(const unsigned int from, const unsigned int to)
{
    static edge* cur = ed;
    cur->to = to;
    cur->pre = head[from];
    head[from] = cur;
    ++cur;
    ++degree[to];
}
inline void add(const unsigned int i)
{
    if (!degree[i])
        (co[i] ? &cq : &mq)->push(i);
}
void redu(queue<unsigned int>& q)
{
    while (!q.empty())
    {
        const unsigned int c = q.front();
        q.pop();
        for (const edge* i = head[c]; i; i = i->pre)
        {
            const unsigned int to = i->to;
            --degree[to];
            add(to);
        }
    }
}
unsigned int topological(const unsigned int n)
{
    unsigned int ret = 0;
    for (unsigned int i = 1; i <= n; ++i)
        add(i);
    while (!mq.empty() || !cq.empty())
    {
        redu(mq);
        if (!cq.empty())
        {
            ++ret;
            redu(cq);
        }
    }
    return ret;
}
int main()
{
#ifndef APTEST
    ios_base::sync_with_stdio(false);
#endif
    unsigned int n, m;
    cin >> n >> m;
    copy_n(istream_iterator<unsigned int>(cin), n, co);
    for (unsigned int i = 0; i < m; ++i)
    {
        unsigned int t1, t2;
        cin >> t1 >> t2;
        addEdge(t2, t1);
    }
    cout << topological(n) << endl;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define ms(a) memset(a,0,sizeof(a))
#define ms_inf(a) memset(a,0x3f,sizeof(a))
#define ms_ninf(a) memset(a,0xcf,sizeof(a))
#define pb push_back
#define mp make_pair
#define fast ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
//#define lc (o<<1)
//#define rc (o<<1|1)
//#include<ext/pb_ds/priority_queue.hpp>
//typedef __gnu_pbds::priority_queue<no> heap;  //��ƫ��
typedef long long ll;
typedef unsigned long long ull;
ull MOD=212370440130137957ll;
int mod=1e9+7;
ll INF=1e18;
const int maxn=1e6+10;
const int maxl=1e2+10;
const double PI=acos(-1.0);
const double eps=1e-8;
mt19937_64 rng((ull)(new char));
queue<int>q[2];
vector<int>g[maxn];
bool a[maxn];
int in[maxn];
int cnt;
void add(int id)
{
	++cnt;
	q[a[id]].push(id);
}
int n;int m;
int main()
{
	fast;cin>>n>>m;_for(t,0,n)cin>>a[t];_for(t,0,m)
	{
		int u,v;cin>>u>>v;g[v].pb(u);++in[u];
	}
	_for(i,0,n)if(!in[i])q[a[i]].push(i),++cnt;int t=0;int as=0;
	while(cnt<n)
	{
		as+=t;
		while(q[t].size())
		{
			int y=q[t].front();q[t].pop();
			for(auto&c:g[y])
			{
				if(!--in[c])add(c);
			}
		}
		t^=1;
	}
	cout<<as;
}


#include<bits/stdc++.h>
using namespace std;
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define ms(a) memset(a,0,sizeof(a))
#define ms_inf(a) memset(a,0x3f,sizeof(a))
#define ms_ninf(a) memset(a,0xcf,sizeof(a))
#define pb push_back
#define mp make_pair
#define fast ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
//#define lc (o<<1)
//#define rc (o<<1|1)
//#include<ext/pb_ds/priority_queue.hpp>
//typedef __gnu_pbds::priority_queue<no> heap;  //��ƫ��
typedef long long ll;
typedef unsigned long long ull;
ull MOD=212370440130137957ll;
int mod=1e9+7;
ll INF=1e18;
const int maxn=1e6+10;
const int maxl=1e2+10;
const double PI=acos(-1.0);
const double eps=1e-8;
mt19937_64 rng((ull)(new char));
queue<int>q[2];
vector<int>g[maxn];
bool a[maxn];
int in[maxn];
int cnt;
void add(int id)
{
	++cnt;
	q[a[id]].push(id);
}
int n;int m;
int main()
{
	fast;cin>>n>>m;_for(t,0,n)cin>>a[t];_for(t,0,m)
	{
		int u,v;cin>>u>>v;g[v].pb(u);++in[u];
	}
	_for(i,0,n)if(!in[i])q[a[i]].push(i),++cnt;int t=0;int as=0;
	while(cnt<n)
	{
		while(q[t].size())
		{
			int y=q[t].front();q[t].pop();
			for(auto&c:g[y])
			{
				if(!--in[c])add(c);
			}
		}
		as+=t;
		t^=1;
	}
	cout<<as;
}


#include<bits/stdc++.h>
using namespace std;
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define ms(a) memset(a,0,sizeof(a))
#define ms_inf(a) memset(a,0x3f,sizeof(a))
#define ms_ninf(a) memset(a,0xcf,sizeof(a))
#define pb push_back
#define mp make_pair
#define fast ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
//#define lc (o<<1)
//#define rc (o<<1|1)
//#include<ext/pb_ds/priority_queue.hpp>
//typedef __gnu_pbds::priority_queue<no> heap;  //��ƫ��
typedef long long ll;
typedef unsigned long long ull;
ull MOD=212370440130137957ll;
int mod=1e9+7;
ll INF=1e18;
const int maxn=1e6+10;
const int maxl=1e2+10;
const double PI=acos(-1.0);
const double eps=1e-8;
mt19937_64 rng((ull)(new char));
queue<int>q[2];
vector<int>g[maxn];
bool a[maxn];
int in[maxn];
int cnt;
void add(int id)
{
	++cnt;
	q[a[id]].push(id);
}
int n;int m;
int main()
{
	fast;cin>>n>>m;_for(t,0,n)cin>>a[t];_for(t,0,m)
	{
		int u,v;cin>>u>>v;g[v].pb(u);++in[u];
	}
	_for(i,0,n)if(!in[i])q[a[i]].push(i),++cnt;int t=0;int as=0;
	while(q[0].size()||q[1].size())
	{
		as+=t;
		while(q[t].size())
		{
			int y=q[t].front();q[t].pop();
			for(auto&c:g[y])
			{
				if(!--in[c])add(c);
			}
		}
		t^=1;
	}
	cout<<as;
}