码迷,mamicode.com
首页 > 其他好文 > 详细

TOJ 3665 方格取数(2)(最大点权独立集)

时间:2018-08-25 23:28:36      阅读:343      评论:0      收藏:0      [点我收藏+]

标签:time   \n   turn   scanf   mil   main   i++   man   out   

描述

给你一个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()<<\n;
103     }
104     return 0;
105 }

 

TOJ 3665 方格取数(2)(最大点权独立集)

标签:time   \n   turn   scanf   mil   main   i++   man   out   

原文地址:https://www.cnblogs.com/taozi1115402474/p/9535779.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!