zoukankan      html  css  js  c++  java
  • 【网络流24题】方格取数问题

    【问题描述】

    在一个有m * n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。对于给定的方格棋盘,按照取数要求编程找出总和最大的数。

    【输入格式】

    第1 行有2 个正整数m和n,分别表示棋盘的行数和列数。
    接下来的m行,每行有n个正整数,表示棋盘方格中的数。

    【输出格式】

    将取数的最大总和输出

    【输入样例】

    3 3
    1 2 3
    3 2 3
    2 3 1

    【输出样例】

    11

    【数据范围】

    1<=N,M<=30

    正解:网络流

    解题报告:对图进行黑白染色,然后就变成了一个二分图,然后就是套结论二分图最大独立集等于权值和减去最小割。

     1 #include <iostream>
     2 #include <iomanip>
     3 #include <cstdlib>
     4 #include <cstdio>
     5 #include <cmath>
     6 #include <cstring>
     7 #include <string>
     8 #include <algorithm>
     9 #define RG register
    10 #define MIN(a,b) a<b?a:b
    11 const int N = 10000;
    12 const int inf = 2147483641;
    13 
    14 using namespace std;
    15 
    16 int gi(){
    17     char ch=getchar();int x=0;
    18     while(ch<'0' || ch>'9') ch=getchar();
    19     while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    20     return x;
    21 }
    22 
    23 struct date{
    24     int from,to,val,fa;
    25 }nn[N];
    26 
    27 int h[N],vis[N],f[N],head[N],cnt=1,jl[N],gg;
    28 int S,T,ans,kk;
    29 
    30 void link(int l,int r,int val){
    31     nn[++cnt]=(date){l,r,val,head[l]},head[l]=cnt;
    32     nn[++cnt]=(date){r,l,0,head[r]},head[r]=cnt;
    33     return;
    34 }
    35 
    36 int bfs(){
    37     for (RG int i=1; i<=gg; ++i)
    38         vis[jl[i]]=0;
    39     int l=0,r=1;gg=0;
    40     h[1]=0,vis[0]=1;
    41     while(l<r){
    42         ++l;
    43         for (RG int i=head[h[l]]; i; i=nn[i].fa){
    44             if (nn[i].val==0 || vis[nn[i].to]) continue;
    45             vis[nn[i].to]=vis[h[l]]+1,jl[++gg]=nn[i].to;
    46             h[++r]=nn[i].to;
    47         }
    48         if (vis[T]) return 1;
    49     }
    50     return 0;
    51 }
    52 
    53 int dinic(int xh,int sum){
    54     if (xh==T) return sum;
    55     RG int s=0;
    56     for (RG int i=head[xh]; i; i=nn[i].fa){
    57         if (vis[nn[i].to]!=vis[xh]+1 || nn[i].val==0) continue;
    58         RG int tmp=dinic(nn[i].to,MIN(sum,nn[i].val));
    59         nn[i].val-=tmp,nn[i^1].val+=tmp;
    60         s+=tmp,sum-=tmp;
    61         if (sum==0) break;
    62     }
    63     if (s==0) vis[xh]=-1;
    64     return s;
    65 }
    66 
    67 int main(){
    68     freopen("x.in","r",stdin);
    69     freopen("x.out","w",stdout);
    70     int m=gi(),n=gi();T=n*m+1;
    71     for (RG int i=1; i<=m; ++i){
    72         RG int k=(i-1)*n;
    73         for (RG int j=1; j<=n; ++j){
    74             f[k+j]=gi();kk+=f[k+j];
    75             if ((i+j-1)&1){
    76                 link(S,k+j,f[k+j]);
    77                 if (j<n)
    78                     link(k+j,k+j+1,inf);
    79                 if (i<m)
    80                     link(k+j,k+j+n,inf);
    81                 if (i>1)
    82                     link(k+j,k+j-n,inf);
    83                 if (j>1)
    84                     link(k+j,k+j-1,inf);
    85             }
    86             else
    87                 link(k+j,T,f[k+j]);
    88         }
    89     }
    90     while(bfs()) ans+=dinic(S,inf);
    91     printf("%d",kk-ans);
    92     return 0;
    93 }
  • 相关阅读:
    ubuntu安装jdk的两种方法
    LeetCode 606. Construct String from Binary Tree (建立一个二叉树的string)
    LeetCode 617. Merge Two Binary Tree (合并两个二叉树)
    LeetCode 476. Number Complement (数的补数)
    LeetCode 575. Distribute Candies (发糖果)
    LeetCode 461. Hamming Distance (汉明距离)
    LeetCode 405. Convert a Number to Hexadecimal (把一个数转化为16进制)
    LeetCode 594. Longest Harmonious Subsequence (最长的协调子序列)
    LeetCode 371. Sum of Two Integers (两数之和)
    LeetCode 342. Power of Four (4的次方)
  • 原文地址:https://www.cnblogs.com/cjk2001/p/6427475.html
Copyright © 2011-2022 走看看