zoukankan      html  css  js  c++  java
  • 「网络流24题」「LuoguP2774」方格取数问题(最大流 最小割

    Description


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

    Input


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

    Output


    程序运行结束时,将取数的最大总和输出

    Sample Input


    3 3
    1 2 3
    3 2 3
    2 3 1

    Sample Output


    11

    Hint


    m,n<=100

    题解


    因为相邻两个数不能同时取的题设要求,像国际象棋棋盘一样染色 得到二分图

    然后S向每个黑点连边,容量为点权

    每个白点向T连边,容量为点权

    最后每个黑点到能到的白点(上下左右)连边,容量为INF(表示这些边中需要割掉一些)

    最后跑一遍最大流 利用最大流最小割定理可得此为最小割(最少要割掉的点权) ans=总点权-最小割

     1 #include<queue>
     2 #include<cmath>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<iostream>
     6 using namespace std;
     7 const int INF=99999999;
     8 struct emm{
     9     int e,f,v;
    10 }a[1000007];
    11 int h[10007];
    12 int tot=1;
    13 void con(int x,int y,int l)
    14 {
    15     if(y==-1)return;
    16     a[++tot].f=h[x];
    17     h[x]=tot;
    18     a[tot].e=y;
    19     a[tot].v=l;
    20     a[++tot].f=h[y];
    21     h[y]=tot;
    22     a[tot].e=x;
    23     return;
    24 }
    25 int tu[107][107];
    26 int num[107][107];
    27 queue<int>q;
    28 int d[10007];
    29 int m,n,s,t;
    30 bool bfs()
    31 {
    32     memset(d,0,sizeof(d));
    33     d[s]=1;
    34     q.push(s);
    35     while(!q.empty())
    36     {
    37         int x=q.front();q.pop();
    38         for(int i=h[x];i;i=a[i].f)
    39         if(!d[a[i].e]&&a[i].v)
    40         {
    41             d[a[i].e]=d[x]+1;
    42             q.push(a[i].e);
    43         }
    44     }
    45     return d[t];
    46 }
    47 int dfs(int x,int al)
    48 {
    49     if(x==t||!al)return al;
    50     int fl=0;
    51     for(int i=h[x];i;i=a[i].f)
    52     if(d[a[i].e]==d[x]+1&&a[i].v)
    53     {
    54         int f=dfs(a[i].e,min(a[i].v,al));
    55         if(f)
    56         {
    57             fl+=f;
    58             al-=f;
    59             a[i].v-=f;
    60             a[i^1].v+=f;
    61             if(!al)break;
    62         }
    63     }
    64     if(!fl)d[x]=-1;
    65     return fl;
    66 }
    67 int main()
    68 {
    69     scanf("%d%d",&m,&n);
    70     s=0,t=m*n+1;
    71     int sum=0;
    72     for(int i=1;i<=m;++i)
    73     for(int j=1;j<=n;++j)
    74     {
    75         scanf("%d",&tu[i][j]);
    76         sum+=tu[i][j];
    77     }
    78     memset(num,-1,sizeof(num));
    79     int tim=0;
    80     for(int i=1;i<=m;++i)
    81     for(int j=1;j<=n;++j)
    82     num[i][j]=++tim;
    83     for(int i=1;i<=m;++i)
    84     for(int j=1;j<=n;++j)
    85     if((i+j)%2==0)con(num[i][j],t,tu[i][j]);
    86     else
    87     {
    88         con(s,num[i][j],tu[i][j]);
    89         con(num[i][j],num[i-1][j],INF);
    90         con(num[i][j],num[i+1][j],INF);
    91         con(num[i][j],num[i][j-1],INF);
    92         con(num[i][j],num[i][j+1],INF);
    93     }
    94     int ans=0;
    95     while(bfs())ans+=dfs(s,INF);
    96     cout<<sum-ans;
    97     return 0;
    98 }
    View Code
     
  • 相关阅读:
    [OpenCV] Ptr类模板
    [OpenCV]Mat类详解
    [C++] Vector用法
    [OpeCV] highgui头文件
    c++中的.hpp文件
    【2017】KK English
    CMake Tutorial & Example
    [g2o]C++图优化库
    Teradata基础教程中的数据库试验环境脚本
    Oracle中对象权限与系统权限revoke
  • 原文地址:https://www.cnblogs.com/qwerta/p/9379760.html
Copyright © 2011-2022 走看看