您的位置:首页 > 理论基础 > 计算机网络

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

2018-08-23 22:27 453 查看

方格取数(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 Happy 2007     把横纵坐标之和按奇偶分成两组,然后对相邻的点连边的话会发现这是一个二分图,我们求得是最大独立集=|V|-最小覆盖集,最小覆盖集可以用网络流来求,左边集合向右边集合的连边容量为inf的边,S向左集合连边,右集合向T连边容量都是格子里的数,然后跑最大流就是 最小覆盖集了。   
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define mp make_pair
#define pb push_back
#define inf 0x3f3f3f3f
#define pii pair<int,int>
int first[3030],tot,S,T;
int cur[3030],d[3030];
bool vis[3030];
struct Edge{
int v,cap,flow,next;
}e[100010];
int fx[4][2]={-1,0,1,0,0,-1,0,1};
void add(int u,int v,int cap){
//cout<<"u="<<u<<' '<<v<<' '<<cap<<endl;
e[tot]=Edge{v,cap,0,first[u]};
first[u]=tot++;
e[tot]=Edge{u,0,0,first[v]};
first[v]=tot++;
}
int a[55][55];
bool bfs(){
memset(vis,0,sizeof(vis));
queue<int>q;
q.push(0);
d[0]=0;
vis[0]=1;
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=first[u];~i;i=e[i].next){
if(!vis[e[i].v] && e[i].cap>e[i].flow){
vis[e[i].v]=1;
d[e[i].v]=d[u]+1;
q.push(e[i].v);
}
}
}
return vis[T];
}
int dfs(int x,int a){
if(x==T || a==0) return a;
int flow=0,f;
for(int &i=cur[x];~i;i=e[i].next){
if(d[x]+1==d[e[i].v] && (f=dfs(e[i].v,min(a,e[i].cap-e[i].flow)))>0){
e[i].flow+=f;
e[i^1].flow-=f;
flow+=f;
a-=f;
if(a==0) break;
}
}
return flow;
}
int solve(){
int ans=0;
while(bfs()){
for(int i=0;i<=T;++i)cur[i]=first[i];
ans+=dfs(0,inf);
}
return ans;
}
int main(){
int n,m,i,j,k;
while(scanf("%d%d",&n,&m)!=EOF){
LL s=0;
memset(first,-1,sizeof(first));
tot=0;
S=0,T=n*m+1;
for(i=1;i<=n;++i){
for(j=1;j<=m;++j){
scanf("%d",&a[i][j]);
s+=a[i][j];
int d1=(i-1)*m+j;
if((i+j)%2==0){
add(S,d1,a[i][j]);

for(k=0;k<4;++k){
int dx=i+fx[k][0];
int dy=j+fx[k][1];
if(dx>0&&dy>0&&dx<=n&&dy<=m){
int d2=(dx-1)*m+dy;
add(d1,d2,inf);
}
}
}
else{
add(d1,T,a[i][j]);
}
}
}
cout<<s-solve()<<endl;
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: