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

    P1528 - 【网络流24题】方格取数问题

    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

    将每个点和它相邻的点标记为不同的颜色,然后把白点和S相连,黑点和T相连,容量为这个点的权值。
    然后把每个白点和它相邻的黑点相连,容量为inf。
    然后问题就转化为求二分图最大点权独立集。
    根据某个定理,答案就等于总权值减去最小割。

    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<cmath>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 1999999999
    using namespace std;
    struct data{
      int nex,to,w;
    }e[12000];
    int head[1000],edge=-1;
    int f[32][32],a[32][32],id[32][32],lev[1000];
    void add(int from,int to,int w){
      e[++edge].nex=head[from];
      e[edge].to=to;
      e[edge].w=w;
      head[from]=edge;
    }
    inline bool bfs(int s,int t){
      queue<int>q;
      q.push(s);
      memset(lev,0,sizeof(lev));
      lev[s]=1;
      while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=e[i].nex)
          if(e[i].w>0 && !lev[e[i].to]){
        lev[e[i].to]=lev[u]+1;
        q.push(e[i].to);
        if(e[i].to==t) return 1;
          }
      }
      return 0;
    }
    int dfs(int s,int t,int k){
      if(s==t) return k;
      int tag=0;
      for(int i=head[s];i!=-1;i=e[i].nex)
        if(e[i].w>0 && lev[e[i].to]==lev[s]+1){
          int d=dfs(e[i].to,t,min(k-tag,e[i].w));
          e[i].w-=d;
          e[i^1].w+=d;
          tag+=d;
          if(tag==k) return tag;
        }
      return tag;
    }
    int dinic(int s,int t){
      int flow=0;
      while(bfs(s,t)) flow+=dfs(s,t,inf);
      return flow;
    }
    int main()
    {
      freopen("!.in","r",stdin);
      freopen("!.out","w",stdout);
      memset(head,-1,sizeof(head));
      int n,m;scanf("%d%d",&n,&m);
      int s=0,t=n*m+1,tot=0;
      for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
          scanf("%d",&a[i][j]),tot+=a[i][j];
      f[1][1]=1;
      for(int i=2;i<=m;i++)
        f[1][i]=f[1][i-1]^1;
      for(int i=2;i<=n;i++)
        for(int j=1;j<=m;j++)
          f[i][j]=f[i-1][j]^1;
      for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) id[i][j]=(i-1)*m+j;
      for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
          int k=id[i][j];
          if(f[i][j]){
        add(s,k,a[i][j]),add(k,s,0);
        if(i-1>0) add(k,id[i-1][j],inf),add(id[i-1][j],k,0);
        if(i+1<=n) add(k,id[i+1][j],inf),add(id[i+1][j],k,0);
        if(j-1>0) add(k,id[i][j-1],inf),add(id[i][j-1],k,0);
        if(j+1<=m) add(k,id[i][j+1],inf),add(id[i][j+1],k,0);
          }
          else add(k,t,a[i][j]),add(t,k,0);
        }
      printf("%d",tot-dinic(s,t));
      return 0;
    }
  • 相关阅读:
    lazyload is not a function解决方式
    APK反编译(Linux环境下)
    讲解图片压缩的文章
    startActivityForResult相关的
    把APP做成libary的注意事项
    ViewPager+Fragment,Fragment会预加载的问题
    FragmentTabHost使用注意
    使用ReTrofit做缓存(结合上拉加载和下拉刷新)
    极光推送,极光IM使用指南(AndroidStudio)
    AndroidStudio使用注意事项
  • 原文地址:https://www.cnblogs.com/pantakill/p/6613464.html
Copyright © 2011-2022 走看看