[ HOJ 2713]Matrix1[网络流] 最大点权独立集问题

题目大意: 一个 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 }

 

posted @ 2017-05-15 13:42  PIPIBoss  阅读(275)  评论(0编辑  收藏  举报