BZOJ 1934: [Shoi2007]Vote 善意的投票( 最小割 )

最小割....

---------------------------------------------------------------------------------

#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;
}

---------------------------------------------------------------------------------

1934: [Shoi2007]Vote 善意的投票

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 1316  Solved: 813
[Submit][Status][Discuss]

Description

幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。 我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?

Input

第一行只有两个整数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不会重复。

Output

只需要输出一个整数,即可能的最小冲突数。

Sample Input

3 3
1 0 0
1 2
1 3
3 2

Sample Output

1

HINT

在第一个例子中,所有小朋友都投赞成票就能得到最优解

Source

 

posted @ 2015-05-24 22:08  JSZX11556  阅读(219)  评论(0编辑  收藏  举报