hdu1569
给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
按国际象棋黑白染色,源点到黑点容量为数字,黑点到它周围的白点容量为无穷,白点到汇点容量为数字,最后答案为总值减去最小割(摘自网上)。
(行+列)= 奇数 黑子 连T
(行+列)= 偶数 白子 连S
没有黑白相邻 , 意味着 ,S 到T没有路可走。 否则 S->黑->白->T 。
<=> 最小的花费把S-T之间的路切开。
U - V 分开最小的权和, 也就是求最小割。
为啥将黑->白权值设为inf ?
这条边“死都存在”,不能人为的移走,那么就是“死都存在”。
意味着不能切割黑->白之间的边。
int main(){
int n , m , i , j , u , v , c , sum ;
while(scanf("%d%d" ,&n ,&m) != EOF){
init() ;
sum = 0 ;
sourse = 0 ;
meet = n*m + 1 ;
for(i = 1 ; i <= n ; i++){
for(j = 1 ; j <= m ; j++){
scanf("%d" ,&c) ;
sum += c ;
u = (i-1) * m + j ;
if((i+j)&1)
add(u , meet , c) ;
else{
add(sourse , u , c) ;
if(i > 1)
add(u , u-m , inf) ;
if(i < n)
add(u , u+m , inf) ;
if(j > 1)
add(u , u-1 , inf) ;
if(j < m)
add(u , u+1 , inf) ;
}
}
}
printf("%d\n" , sum - maxflow()) ;
}
return 0 ;
}
hdu 3657
题目描述:n*m的矩阵,每个位置都有一个正数,一开始你的分数是0,当你取走一个数字时,你的分数增加那个分数。如果你取完数字后,新出现了2个相邻的都是空的格子,那么你的分数减少2 * ( x & y),x,y是那两个格子的原始数值。
同时有一些附加条件,有一些格子的数字是必须拿走的。
-----------------------
同上题
----------------------
为啥将黑->白权值设为2*(x&y) ?
因为切割黑-白之间的路可以“人为的移走”,不是“死都存在”的边。
对于必须选择的棋子,将权值设为inf。也就是说最小割集不会选择此边<=>此点必选。
int w[58][58] ;
bool is[58][58] ;
int main(){
int n , m , i , j , k , u , sum ;
while(cin>>n>>m>>k){
sum = 0 ;
init() ;
sourse = 0 , meet = n*m + 1 ;
for(i = 1 ; i <= n ; i++){
for(j = 1 ; j <= m ; j++){
scanf("%d" ,&w[i][j]) ;
sum += w[i][j] ;
}
}
memset(is , 0 , sizeof(is)) ;
while(k--){
scanf("%d%d" ,&i ,&j) ;
is[i][j] = 1 ;
}
for(i = 1 ; i <= n ; i++){
for(j = 1 ; j <= m ; j++){
u = (i-1)*m + j ;
if((i+j)&1){
if(is[i][j])
add(u , meet , inf) ;
else
add(u , meet , w[i][j]) ;
}
else{
if(is[i][j])
add(sourse , u , inf) ;
else
add(sourse , u , w[i][j]) ;
if(i > 1)
add(u , u-m , 2*(w[i][j]&w[i-1][j])) ;
if(i < n)
add(u , u+m , 2*(w[i][j]&w[i+1][j])) ;
if(j > 1)
add(u , u-1 , 2*(w[i][j]&w[i][j-1])) ;
if(j < m)
add(u , u+1 , 2*(w[i][j]&w[i][j+1])) ;
}
}
}
printf("%d\n" , sum - maxflow()) ;
}
return 0 ;
}