题目大意: 一个 N*M 的网格,每个单元都有一块价值 Cij 的宝石。问最多能取多少价值的宝石且任意两块宝石不相邻。(1 <= N, M <= 50, 0 <= Cij <= 40000)
建图方法:
先对网格进行黑白染色,
然后所有黑点到S有一条容量为Cij的边,
白点到T有一条容量为Cij的边,
黑点和相邻的白点有一条容量为INF的边.
最后答案就是 所有的Cij之和减去最小割
自己的理解:每一条边如果流满相当于放弃这一种宝石,并且所以最小割保证放弃的价值最少。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdlib> 6 using namespace std; 7 const int N=8005,INF=1999999999; 8 int gi(){ 9 int str=0;char ch=getchar(); 10 while(ch>'9' || ch<'0')ch=getchar(); 11 while(ch>='0' && ch<='9')str=str*10+ch-48,ch=getchar(); 12 return str; 13 } 14 int head[N],num=1; 15 struct Lin{ 16 int next,to,dis; 17 }a[N*100]; 18 void init(int x,int y,int z){ 19 a[++num].next=head[x]; 20 a[num].to=y; 21 a[num].dis=z; 22 head[x]=num; 23 a[++num].next=head[y]; 24 a[num].to=x; 25 a[num].dis=0; 26 head[y]=num; 27 } 28 int val[52][52],id[52][52],ids=0,S=0,T,ans=0; 29 int mx[4]={0,0,1,-1},my[4]={1,-1,0,0}; 30 int q[N],dep[N]; 31 bool bfs() 32 { 33 memset(dep,0,sizeof(dep)); 34 int x,u,t=0,sum=1; 35 q[1]=S;dep[S]=1; 36 while(t!=sum) 37 { 38 x=q[++t]; 39 for(int i=head[x];i;i=a[i].next){ 40 u=a[i].to; 41 if(dep[u]||a[i].dis<=0)continue; 42 dep[u]=dep[x]+1;q[++sum]=u; 43 } 44 } 45 return dep[T]; 46 } 47 int dfs(int x,int flow) 48 { 49 if(x==T || !flow)return flow; 50 int u,tmp,sum=0; 51 for(int i=head[x];i;i=a[i].next){ 52 u=a[i].to; 53 if(dep[u]!=dep[x]+1 || a[i].dis<=0)continue; 54 tmp=dfs(u,min(flow,a[i].dis)); 55 a[i].dis-=tmp;a[i^1].dis+=tmp; 56 sum+=tmp;flow-=tmp; 57 if(!flow)break; 58 } 59 return sum; 60 } 61 int maxflow(){ 62 int tot=0,tmp; 63 while(bfs()){ 64 tmp=dfs(S,INF); 65 while(tmp)tot+=tmp,tmp=dfs(S,INF); 66 } 67 return tot; 68 } 69 void work() 70 { 71 int n=gi(),m=gi(),flag,xx,yy; 72 T=n*m+1; 73 for(int i=1;i<=n;i++) 74 for(int j=1;j<=m;j++){ 75 val[i][j]=gi();id[i][j]=++ids;ans+=val[i][j]; 76 } 77 for(int i=1;i<=n;i++) 78 for(int j=1;j<=m;j++){ 79 flag=((i+j)&1); 80 if(flag)init(S,id[i][j],val[i][j]); 81 else init(id[i][j],T,val[i][j]); 82 if(!flag)continue; 83 for(int k=0;k<4;k++){ 84 xx=i+mx[k];yy=j+my[k]; 85 if(xx>n || xx<1 || yy>m || yy<1)continue; 86 init(id[i][j],id[xx][yy],INF); 87 } 88 } 89 printf("%d\n",ans-maxflow()); 90 } 91 void Clear(){ 92 memset(head,0,sizeof(head)); 93 num=1;ids=0;ans=0; 94 } 95 int main() 96 { 97 int TT=gi(); 98 while(TT--){ 99 work(); 100 Clear(); 101 } 102 }