zoukankan      html  css  js  c++  java
  • TZOJ 3665 方格取数(2)(最大点权独立集)

    描述

    给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
    从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。

    输入

    包括多个测试实例,每个测试实例包括2整数m,n和m行n列的非负数(m<=50,n<=50)

    输出

    对于每个测试实例,输出可能取得的最大的和

    样例输入

    3 3
    75 15 21
    75 15 28
    34 70 5

    样例输出

    188

    题意

    如上

    题解

    最大点权独立集=总权值-最小点权覆盖

    用最小割跑出来的是最小点权覆盖,再用sum-最小点权覆盖

    把图黑白染色,黑色点连源点S流量a[i][j],白色点连汇点T流量a[i][j],然后每个相邻的黑白点连黑白边流量INF,跑最小割即可

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int maxn=1e5+5;
      5 const int maxm=2e5+5;
      6 int n,m,S,T;
      7 int deep[maxn],q[400000];
      8 int FIR[maxn],TO[maxm],CAP[maxm],COST[maxm],NEXT[maxm],tote;
      9 
     10 void add(int u,int v,int cap)
     11 {
     12     TO[tote]=v;
     13     CAP[tote]=cap;
     14     NEXT[tote]=FIR[u];
     15     FIR[u]=tote++;
     16 
     17     TO[tote]=u;
     18     CAP[tote]=0;
     19     NEXT[tote]=FIR[v];
     20     FIR[v]=tote++;
     21 }
     22 bool bfs()
     23 {
     24     memset(deep,0,sizeof deep);
     25     deep[S]=1;q[1]=S;
     26     int head=0,tail=1;
     27     while(head!=tail)
     28     {
     29         int u=q[++head];
     30         for(int v=FIR[u];v!=-1;v=NEXT[v])
     31         {
     32             if(CAP[v]&&!deep[TO[v]])
     33             {
     34                 deep[TO[v]]=deep[u]+1;
     35                 q[++tail]=TO[v];
     36             }
     37         }
     38     }
     39     return deep[T];
     40 }
     41 int dfs(int u,int fl)
     42 {
     43     if(u==T)return fl;
     44     int f=0;
     45     for(int v=FIR[u];v!=-1&&fl;v=NEXT[v])
     46     {
     47         if(CAP[v]&&deep[TO[v]]==deep[u]+1)
     48         {
     49             int Min=dfs(TO[v],min(fl,CAP[v]));
     50             CAP[v]-=Min;CAP[v^1]+=Min;
     51             fl-=Min;f+=Min;
     52         }
     53     }
     54     if(!f)deep[u]=-2;
     55     return f;
     56 }
     57 int maxflow()
     58 {
     59     int ans=0;
     60     while(bfs())
     61         ans+=dfs(S,1<<28);
     62     return ans;
     63 }
     64 void init()
     65 {
     66     tote=0;
     67     memset(FIR,-1,sizeof FIR);
     68 }
     69 int N,M,a[55][55],color[55][55],has[55][55],tot,sum,f;
     70 int main()
     71 {
     72     while(cin>>N>>M)
     73     {
     74         init();
     75         memset(color,0,sizeof color);
     76         tot=sum=0;
     77         for(int i=1;i<=N;i++)
     78         {
     79             if(i&1)f=1;
     80             else f=-1;
     81             for(int j=1;j<=M;f*=-1,j++)
     82             {
     83                 scanf("%d",&a[i][j]);
     84                 sum+=a[i][j];
     85                 has[i][j]=tot++;
     86                 color[i][j]=f;
     87             }
     88         }
     89         S=tot,T=S+1;
     90         for(int i=1;i<=N;i++)
     91             for(int j=1;j<=M;j++)
     92             {
     93                 if(color[i][j]==1)
     94                     add(S,has[i][j],a[i][j]);
     95                 else
     96                     add(has[i][j],T,a[i][j]);
     97                 if(color[i-1][j]==-1)add(has[i][j],has[i-1][j],1<<28);
     98                 if(color[i+1][j]==-1)add(has[i][j],has[i+1][j],1<<28);
     99                 if(color[i][j-1]==-1)add(has[i][j],has[i][j-1],1<<28);
    100                 if(color[i][j+1]==-1)add(has[i][j],has[i][j+1],1<<28);
    101             }
    102         cout<<sum-maxflow()<<'
    ';
    103     }
    104     return 0;
    105 }
  • 相关阅读:
    POJ 1300 Open Door
    POJ 2230 Watchcow
    codevs 1028 花店橱窗布置
    codevs 1021 玛丽卡
    codevs 1519 过路费
    codevs 3287 货车运输
    codevs 3305 水果姐逛水果街二
    codevs 1036 商务旅行
    codevs 4605 LCA
    POJ 1330 Nearest Common Ancestors
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/9535779.html
Copyright © 2011-2022 走看看