首页 > 代码库 > hdu 1565 方格取数(2)(网络流之最大点权独立集)

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\n",sum-G.get_ans());
54     }
55     return 0;
56 }
View Code

 

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