hdu1569-方格取数-二分图网络流

方格取数(2)

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7211    Accepted Submission(s): 2311


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

 

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

 

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

 

Sample Input
3 3 75 15 21 75 15 28 34 70 5
 

 

Sample Output
188
 

 

Author
ailyanlu
 

 

Source
 
  把横纵坐标之和按奇偶分成两组,然后对相邻的点连边的话会发现这是一个二分图,我们求得是最大独立集=|V|-最小覆盖集,最小覆盖集可以用网络流来求,左边集合向右边集合的连边容量为inf的边,S向左集合连边,右集合向T连边容量都是格子里的数,然后跑最大流就是
最小覆盖集了。
  
 1 #include<bits/stdc++.h> 
 2 using namespace std;  
 3 #define LL long long 
 4 #define mp make_pair
 5 #define pb push_back
 6 #define inf 0x3f3f3f3f
 7 #define pii pair<int,int>
 8 int first[3030],tot,S,T;
 9 int cur[3030],d[3030];
10 bool vis[3030];
11 struct Edge{
12     int v,cap,flow,next;
13 }e[100010];
14 int fx[4][2]={-1,0,1,0,0,-1,0,1};
15 void add(int u,int v,int cap){
16     //cout<<"u="<<u<<' '<<v<<' '<<cap<<endl;
17     e[tot]=Edge{v,cap,0,first[u]};
18     first[u]=tot++;
19     e[tot]=Edge{u,0,0,first[v]};
20     first[v]=tot++;
21 }
22 int a[55][55];
23 bool bfs(){
24     memset(vis,0,sizeof(vis));
25     queue<int>q;
26     q.push(0);
27     d[0]=0;
28     vis[0]=1;
29     while(!q.empty()){
30         int u=q.front();
31         q.pop();
32         for(int i=first[u];~i;i=e[i].next){
33             if(!vis[e[i].v] && e[i].cap>e[i].flow){
34                 vis[e[i].v]=1;
35                 d[e[i].v]=d[u]+1;
36                 q.push(e[i].v);
37             }
38         }
39     }
40     return vis[T];
41 }
42 int dfs(int x,int a){
43     if(x==T || a==0) return a;
44     int flow=0,f;
45     for(int &i=cur[x];~i;i=e[i].next){
46         if(d[x]+1==d[e[i].v] && (f=dfs(e[i].v,min(a,e[i].cap-e[i].flow)))>0){
47             e[i].flow+=f;
48             e[i^1].flow-=f;
49             flow+=f;
50             a-=f;
51             if(a==0) break;
52         }
53     }
54     return flow;
55 }
56 int solve(){
57     int ans=0;
58     while(bfs()){
59         for(int i=0;i<=T;++i)cur[i]=first[i];
60         ans+=dfs(0,inf);
61     }
62     return ans;
63 }
64 int main(){
65     int n,m,i,j,k;
66     while(scanf("%d%d",&n,&m)!=EOF){
67         LL s=0;
68         memset(first,-1,sizeof(first));
69         tot=0;
70         S=0,T=n*m+1;
71         for(i=1;i<=n;++i){
72             for(j=1;j<=m;++j){
73                 scanf("%d",&a[i][j]);
74                 s+=a[i][j];
75                 int d1=(i-1)*m+j;
76                 if((i+j)%2==0){
77                     add(S,d1,a[i][j]);
78                     
79                     for(k=0;k<4;++k){
80                         int dx=i+fx[k][0];
81                         int dy=j+fx[k][1];
82                         if(dx>0&&dy>0&&dx<=n&&dy<=m){
83                             int d2=(dx-1)*m+dy;
84                             add(d1,d2,inf);
85                         }
86                     }
87                 }
88                 else{
89                     add(d1,T,a[i][j]);
90                 }
91             }
92         }
93         cout<<s-solve()<<endl;
94     }
95     return 0;
96 }

 

posted @ 2018-08-23 22:27  *zzq  阅读(158)  评论(0编辑  收藏  举报