• hdu 1565 方格取数(2)(网络流之最大点权独立集)


    题目链接:hdu 1565 方格取数(2)

    题意:

    有一个n*m的方格,每个方格有一个数,现在让你选一些数。使得和最大。

    选的数不能有相邻的。

    题解:

    我们知道对于普通二分图来说,最大独立点集 + 最小点覆盖集 = 总点数,类似的,对于有权的二分图来说,有:

    最大点权独立集 + 最小点权覆盖集 = 总点权和,

    这个题很明显是要求 最大点权独立集 ,现在 总点权 已知,我们只要求出来 最小点权覆盖集 就好了,我们可以这样建图,

    1,对矩阵中的点进行黑白着色(相邻的点颜色不同),从源点向黑色的点连一条边,权值为该黑色点的权值,

    2,从白色的点向汇点连一条边,权值为该白色点的权值,

    3,然后,对于每一对相邻的黑白点,从黑点向白点连一条边,权值为无穷大。

    最后求最小割(最大流),即为最小点权覆盖集。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;i++)
     3 using namespace std;
     4 
     5 const int N=2550,inf=~0U>>2,M=1e6+7;
     6 struct edge{int t,f;edge*nxt,*pair;}*g[N],*d[N],pool[M],*cur=pool;
     7 struct ISAP{
     8     int n,m,i,S,T,h[N],gap[N],maxflow;
     9     void init(int ss,int tt){for(S=ss,T=tt,cur=pool,i=1;i<=T;i++)g[i]=d[i]=NULL,h[i]=gap[i]=0;}
    10     void add(int s,int t,int f){
    11         edge*p=cur++;p->t=t,p->f=f,p->nxt=g[s],g[s]=p;
    12         p=cur++,p->t=s,p->f=0,p->nxt=g[t],g[t]=p;
    13         g[s]->pair=g[t],g[t]->pair=g[s];
    14     }
    15     int sap(int v,int flow){
    16         if(v==T)return flow;
    17         int rec=0;
    18         for(edge*p=d[v];p;p=p->nxt)if(h[v]==h[p->t]+1&&p->f){
    19         int ret=sap(p->t,min(flow-rec,p->f));
    20         p->f-=ret;p->pair->f+=ret;d[v]=p;
    21         if((rec+=ret)==flow)return flow;
    22         }
    23         if(!(--gap[h[v]]))h[S]=T;
    24         gap[++h[v]]++;d[v]=g[v];
    25         return rec;
    26     }
    27     int get_ans(){
    28         for(gap[maxflow=0]=T,i=1;i<=T;i++)d[i]=g[i];
    29         while(h[S]<T)maxflow+=sap(S,inf);
    30         return maxflow;
    31     }
    32 }G;
    33 
    34 int n,m,mp[55][55],sum,dir[][2]={1,0,-1,0,0,1,0,-1};
    35 
    36 int main()
    37 {
    38     while(~scanf("%d%d",&n,&m))
    39     {
    40         G.init(n*m+1,n*m+2);sum=0;
    41         F(i,1,n)F(j,1,m)scanf("%d",&mp[i][j]),sum+=mp[i][j];
    42         F(i,1,n)F(j,1,m)
    43         {
    44             if((i+j)&1){G.add((i-1)*m+j,G.T,mp[i][j]);continue;}
    45             G.add(G.S,(i-1)*m+j,mp[i][j]);
    46             F(ii,0,3)
    47             {
    48                 int x=i+dir[ii][0],y=j+dir[ii][1];
    49                 if(x<1||x>n||y<1||y>m)continue;
    50                 G.add((i-1)*m+j,(x-1)*m+y,inf);
    51             }
    52         }
    53         printf("%d
    ",sum-G.get_ans());
    54     }
    55     return 0;
    56 }
    View Code
  • 相关阅读:
    js 小数取整的函数
    VS2015 Apache Cordova
    C# 标签(条码)
    异步提交form的时候利用jQuery validate实现表单验证
    调试javascript
    Chrome 控制台console的用法
    MvcPager分页控件以适用Bootstrap
    更好理解接口
    为什么上班一天都是坐着,但仍会疲惫不堪?(转)
    如何解决空虚感?(转)
  • 原文地址:https://www.cnblogs.com/bin-gege/p/6914656.html
Copyright © 2020-2023  润新知