BZOJ 1475: 方格取数( 网络流 )

本来想写道水题....结果调了这么久!就是一个 define 里面少加了个括号 !

二分图最大点权独立集...黑白染色一下 , 然后建图 :

S -> black_node , white_node -> T , 流量都为点权 . 然后 black_node -> white_node ( 两点有公共边 ) , 流量为 +oo , 然后 answer = ∑ w( i ) ( i ∈ V ) - maxflow

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

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<iostream>

#define rep( i , n ) for( int i = 0 ; i < n ; ++i )

#define clr( x , c ) memset( x , c , sizeof( x ) )

#define id( x , y ) ( ( x ) * n + y + 1 )

using namespace std;

const int inf = 0x7fffffff;

const int maxn = 1000;

struct edge {

int to , cap;

edge *next , *rev;

} E[ maxn << 3 ] , *pt = E , *head[ maxn ];

inline void add_edge( int u , int v , int w ) {

pt -> to = v;

pt -> cap = w;

pt -> next = head[ u ];

head[ u ] = pt++;

pt -> to = u;

pt -> cap = 0;

pt -> next = head[ v ];

head[ v ] = pt++;

head[ u ] -> rev = head[ v ];

head[ v ] -> rev = head[ u ];

}

int h[ maxn ] , cnt[ maxn ] , S , T , N;

edge *cur[ maxn ] , *p[ maxn ];

int maxFlow() {

clr( h , 0 ) , clr( cnt , 0 );

cnt[ 0 ] = N;

rep( i , N ) cur[ i ] = head[ i ];

int flow = 0 , A = inf;

edge* e;

for( int x = S ; h[ S ] < N ; ) {

for( e = cur[ x ] ; e ; e = e -> next )

if( h[ e -> to ] + 1 == h[ x ] && e -> cap ) break;

if( e ) {

A = min( A , e -> cap );

p[ e -> to ] = cur[ x ] = e;

if( ( x = e -> to ) == T ) {

for( ; x != S ; x = p[ x ] -> rev -> to ) {

p[ x ] -> cap -= A;

p[ x ] -> rev -> cap += A;

}

flow += A;

A = inf;

}

} else {

if( ! --cnt[ h[ x ] ] ) break;

h[ x ] = N;

for( e = head[ x ] ; e ; e = e -> next )

if( e -> cap && h[ e -> to ] + 1 < h[ x ] ) {

h[ x ] = h[ e -> to ] + 1;

cur[ x ] = e;

}

cnt[ h[ x ] ]++;

if( x != S ) x = p[ x ] -> rev -> to;

}

}

return flow;

}

int main(){

freopen( "test.in" , "r" , stdin );

clr( head , 0 );

int ans = 0 , n;

cin >> n;

S = 0 , T = n * n + 1 , N = T + 1;

rep( i , n )

rep( j , n ) {

int w;

scanf( "%d" , &w );

ans += w;

if( ( i + j ) & 1 ) {

add_edge( S , id( i , j ) , w );

if( i ) add_edge( id( i , j ) , id( i - 1 , j ) , inf );

if( j ) add_edge( id( i , j ) , id( i , j - 1 ) , inf );

if( i + 1 < n ) add_edge( id( i , j ) , id( i + 1 , j ) , inf );

if( j + 1 < n ) add_edge( id( i , j ) , id( i , j + 1 ) , inf );

} else

add_edge( id( i , j ) , T , w );

}

cout << ans - maxFlow() << "\n";

return 0;

}

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

1475: 方格取数

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 616  Solved: 323
[Submit][Status][Discuss]

Description

在一个n*n的方格里,每个格子里都有一个正整数。从中取出若干数,使得任意两个取出的数所在格子没有公共边,且取出的数的总和尽量大。

Input

第一行一个数n;(n<=30) 接下来n行每行n个数描述一个方阵

Output

仅一个数,即最大和

Sample Input

2
1 2
3 5

Sample Output

6

HINT

Source

时间: 2024-10-05 04:24:51

BZOJ 1475: 方格取数( 网络流 )的相关文章

1475: 方格取数

1475: 方格取数 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 578  Solved: 309[Submit][Status][Discuss] Description 在一个n*n的方格里,每个格子里都有一个正整数.从中取出若干数,使得任意两个取出的数所在格子没有公共边,且取出的数的总和尽量大. Input 第一行一个数n:(n<=30) 接下来n行每行n个数描述一个方阵 Output 仅一个数,即最大和 Sample Input 2 1 2

方格取数(网络流24题)

题意 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.对于给定的方格棋盘,按照取数要求编程找出总和最大的数. 题解 方格是常见的二分图(疑问脸).所以考虑先染色,相邻的格子颜色不同,这样就分成了二分图,先假设全选,然后跑最小割就好了,割掉就是不选. #include<bits/stdc++.h> using namespace std; const int maxn=10005;

hdu 1569 方格取数(2) 网络流 最大点权独立集

方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5146    Accepted Submission(s): 1610 Problem Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的

【网络流】hdu 1569 方格取数(2)

/* 和1565一样: 总点数的权 - 最小覆盖点集 = 最大独立集 -------------------------------------- void add(int u, int v, int f)加边 { e[ct].u = u; e[ct].v = v; e[ct].f = f; next[ct] = first[u]; first[u] = ct++; e[ct].u = v; e[ct].v = u; e[ct].f = 0; next[ct] = first[v]; first

NEU 1458 方格取数(网络流之费用流)

题目地址:NEU 1458 跟杭电上的那两个方格取数不太一样..这个可以重复,但是取和的时候只能加一次.建图思路基本一会就出来.同样的拆点,只不过这题需要再拆个边,其中一条费用0,另一条费用为那个点处的值.流量都限制为1.然后剩下的都跟杭电上的那两个差不多了.因为把数组开小了WA了好几发..(我前面居然还专门检查了一下数组大小,居然当时还认为没开小...对自己无语..) 代码如下: #include <iostream> #include <stdio.h> #include &l

XTU 二分图和网络流 练习题 C. 方格取数(1)

C. 方格取数(1) Time Limit: 5000ms Memory Limit: 32768KB 64-bit integer IO format: %I64d      Java class name: Main 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大. Input 包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20) Output 对

734. [网络流24题] 方格取数问题 二分图点权最大独立集/最小割/最大流

?问题描述:在一个有m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.?编程任务:对于给定的方格棋盘,按照取数要求编程找出总和最大的数.?数据输入:由文件grid.in提供输入数据.文件第1 行有2 个正整数m和n,分别表示棋盘的行数和列数.接下来的m行,每行有n个正整数,表示棋盘方格中的数. [问题分析] 二分图点权最大独立集,转化为最小割模型,从而用最大流解决. [建模方法] 首先把棋盘黑白

LiberOJ #6007. 「网络流 24 题」方格取数 最小割 最大点权独立集 最大流

#6007. 「网络流 24 题」方格取数 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 在一个有 m×n m \times nm×n 个方格的棋盘中,每个方格中有一个正整数. 现要从方格中取数,使任意 2 22 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法. 输入格式 文件第 1 11 行有 2 22 个正整数 m mm 和 n nn,分别表示棋盘的行数和列数

线性规划与网络流9 方格取数

算法实现题 8-9 方格取数问题(习题 8-20)?问题描述:在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.?编程任务:对于给定的方格棋盘,按照取数要求编程找出总和最大的数.?数据输入:由文件 input.txt 提供输入数据.文件第 1 行有 2 个正整数 m和 n,分别表示棋盘的行数和列数.接下来的 m行,每行有 n 个正整数,表示棋盘方格中的数.?结果输出:程序运行结束时,