---------------------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cctype>
 
#define rep( i , n ) for( int i = 0 ; i < n ; ++i )
#define clr( x , c ) memset( x , c , sizeof( x ) )
#define Rep( i , n ) for( int i = 1 ; i <= n ; ++i )
 
using namespace std;
 
const int maxn = 300 + 5;
 
struct edge {
	int to , cap;
	edge *next , *rev;
};
 
edge* pt;
edge* head[ maxn ];
edge EDGE[ maxn * maxn << 1 ];
 
void init() {
	pt = EDGE;
	clr( head , 0 );
}
 
inline void add( int u , int v , int d ) {
	pt -> to = v;
	pt -> cap = d;
	pt -> next = head[ u ];
	head[ u ] = pt++;
}
 
inline void add_edge( int u , int v , int d ) {
	add( u , v , d );
	add( v , u , 0 );
	head[ u ] -> rev = head[ v ];
	head[ v ] -> rev = head[ u ];
}
 
edge *p[ maxn ] , *cur[ maxn ];
int d[ maxn ] , cnt[ maxn ];
 
int maxFlow( int S , int T , int N ) {
	
	clr( d , 0 );
	clr( cnt , 0 );
	cnt[ 0 ] = N;
	
	rep( i , N ) cur[ i ] = head[ i ];
	
	const int INF = 0x7fffffff;
	
	int x = S , flow = 0 , A = INF;
	
	edge* e;
	
	while( d[ S ] < N ) {
		
		for( e = cur[ x ] ; e ; e = e -> next )
		    if( e -> cap > 0 && d[ e -> to ] + 1 == d[ x ] ) break;
		    
		if( e ) {
			
			p[ e -> to ] = cur[ x ] = e;
			
			A = min( A , e -> cap );
			
			x = e -> to;
			
			if( x == T ) {
				
				while( x != S ) {
					
					p[ x ] -> cap -= A;
					p[ x ] -> rev -> cap += A;
					
					x = p[ x ] -> rev -> to;
					
				}
				
				flow += A;
				A = INF;
				
			}
			
		} else {
			
			if( ! --cnt[ d[ x ] ] ) break;
			
			d[ x ] = N;
			
			for( e = head[ x ] ; e ; e = e -> next ) if( d[ x ] > d[ e -> to ] + 1 && e -> cap > 0 ) {
				
				d[ x ] = d[ e -> to ] + 1;
				
				cur[ x ] = e;
				
			}
			
			cnt[ d[ x ] ]++;
			
			if( x != S ) x = p[ x ] -> rev -> to;
			
		}
		
	}
	
	return flow;
	
}
 
int main() {
	
	init();
	
	int n , m;
	cin >> n >> m;
	
	int s = 0 , t = n + 1;
	
	Rep( i , n ) {
		
		int x;
		
		scanf( "%d" , &x );
		
		x ? add_edge( s , i , 1 ) : add_edge( i , t , 1 );
		
	}
	
	while( m-- ) {
		
		int u , v;
		
		scanf( "%d%d" , &u , &v );
		
		add_edge( u , v , 1 );
		add_edge( v , u , 1 );
		
	}
		
	cout << maxFlow( s , t , t + 1 ) << "\n";
	
	return 0;
}
---------------------------------------------------------------------------------
幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。 我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?
第一行只有两个整数n,m,保证有2≤n≤300,1≤m≤n(n-1)/2。其中n代表总人数,m代表好朋友的对数。文件第二行有n个整数,第i个整数代表第i个小朋友的意愿,当它为1时表示同意睡觉,当它为0时表示反对睡觉。接下来文件还有m行,每行有两个整数i,j。表示i,j是一对好朋友,我们保证任何两对i,j不会重复。