您的位置:首页 > 编程语言 > Go语言

HDOJ 3820 - Golden Eggs 构图最小割(类似二分图的最大独立点权集)

2013-09-09 17:15 405 查看
题意:

给了N*M的方阵...每个格子里可以放金蛋或者银蛋或者空着..同时有相应的得分..但是若两个有共同边的格子放了相同种类的蛋..当都是金蛋时.得分-G..当都是银蛋时..得分-S..问最多能得多少分...

题解:

看了别人的思路才A的..先说一下解题方法..这种相邻冲突的问题一般都是分为奇数格和偶数格(按照<x,y>的x+y的奇偶来分)了..

本题:

1、每个点p拆成两点..p<<1代表其放了金蛋..p<<1|1代表其放了银蛋

2、对于所有奇数点,超级汇点往其金蛋(p<<1)做边容量为其放金蛋能获得的分数,其金蛋(p<<1)往其银蛋(p<<1|1)做边容量为inf,其银蛋(p<<1|1)往超级汇点做边容量为其放银蛋能获得的分数

3、对于所有偶数点,超级汇点往其银蛋(p<<1|1)做边容量为其放银蛋能获得的分数,其银蛋(p<<1|1)往其金蛋(p<<1)做边容量为inf,其金蛋(p<<1)往超级汇点做边容量为其放金蛋能获得的分数

4、对于所有相邻的格子..奇数点的金蛋(p<<1)往偶数点的金蛋(p<<1)做边..容量为G...偶数点的银蛋(p<<1|1)往奇数点的银蛋(p<<1|1)做边..容量为S

5、用所有点放银蛋放金蛋的分数之和sum-该图的最大流就是答案..

自我总结:

这题类似于HDU1569..比如把条件修改为任意相邻的不能相同..就完全一样了...

注意的是...本题在统计sum时只统计了各点金蛋银蛋的分数..所以构图跑最大流找出最小割后..有些割边是G/S..由于sum中没有..减去它就像等于-G/-S...

Program:

#include<iostream>    
#include<algorithm>    
#include<stdio.h>    
#include<string.h>  
#include<time.h> 
#include<map> 
#include<math.h>    
#include<queue>    
#define MAXN 100005 
#define MAXM 2000005   
#define oo 1000000007    
#define ll long long    
using namespace std;   
struct Dinic            
{            
       struct node          
       {           
             int c,u,v,next;          
       }edge[MAXM];          
       int ne,head[MAXN];          
       int cur[MAXN], ps[MAXN], dep[MAXN];          
       void initial()          
       {          
             ne=2;          
             memset(head,0,sizeof(head));           
       }          
       void addedge(int u, int v,int c)          
       {           
             edge[ne].u=u,edge[ne].v=v,edge[ne].c=c,edge[ne].next=head[u];          
             head[u]=ne++;          
             edge[ne].u=v,edge[ne].v=u,edge[ne].c=0,edge[ne].next=head[v];          
             head[v]=ne++;          
       }          
       int MaxFlow(int s,int t)          
       {                               
             int tr, res = 0;          
             int i,j,k,f,r,top;          
             while(1)          
             {          
                    memset(dep, -1, sizeof(dep));          
                    for(f=dep[ps[0]=s]=0,r=1;f!= r;)          
                       for(i=ps[f++],j=head[i];j;j=edge[j].next)          
                         if(edge[j].c&&dep[k=edge[j].v]==-1)          
                         {          
                               dep[k]=dep[i]+1;          
                               ps[r++]=k;          
                               if(k == t){  f=r; break;  }          
                         }          
                    if(dep[t]==-1) break;          
                    memcpy(cur,head,sizeof(cur));          
                    i=s,top=0;          
                    while(1)          
                    {          
                         if(i==t)          
                         {          
                               for(tr=oo,k=0;k<top;k++)          
                                  if(edge[ps[k]].c<tr)          
                                     tr=edge[ps[f=k]].c;          
                               for(k=0;k<top;k++)          
                               {          
                                     edge[ps[k]].c-=tr;          
                                     edge[ps[k]^1].c+=tr;          
                               }          
                               i=edge[ps[top=f]].u;          
                               res+= tr;          
                         }          
                         for(j=cur[i];cur[i];j=cur[i]=edge[cur[i]].next)           
                             if(edge[j].c && dep[i]+1==dep[edge[j].v]) break;           
                         if(cur[i])  ps[top++]=cur[i],i=edge[cur[i]].v;           
                         else          
                         {          
                                 if(!top) break;          
                                 dep[i]=-1;          
                                 i=edge[ps[--top]].u;          
                         }          
                   }          
             }          
             return res;          
      }          
}T;      
int main()   
{             
      int N,M,G,S,s,e,C,cases,x,i,j,p,sum; 
      scanf("%d",&C);
      for (cases=1;cases<=C;cases++)
      {
                scanf("%d%d%d%d",&N,&M,&G,&S);
                s=(N*M)<<2,e=s+1,T.initial(),sum=0;
                for (i=0;i<N;i++)
                   for (j=0;j<M;j++)
                   {
                          scanf("%d",&x),sum+=x,p=i*M+j; 
                          if ((i+j)%2) 
                          {
                                   T.addedge(s,p<<1,x),T.addedge(p<<1,p<<1|1,oo);
                                   if (i) 
                                      T.addedge(p<<1,(p-M)<<1,G),T.addedge((p-M)<<1|1,p<<1|1,S);
                                   if (j)
                                      T.addedge(p<<1,(p-1)<<1,G),T.addedge((p-1)<<1|1,p<<1|1,S);
                                   if (i!=N-1)
                                      T.addedge(p<<1,(p+M)<<1,G),T.addedge((p+M)<<1|1,p<<1|1,S);
                                   if (j!=M-1)
                                      T.addedge(p<<1,(p+1)<<1,G),T.addedge((p+1)<<1|1,p<<1|1,S);
                          }
                             else  T.addedge(p<<1,e,x),T.addedge(p<<1|1,p<<1,oo);
                   }
                for (i=0;i<N;i++)
                   for (j=0;j<M;j++)
                   {
                          scanf("%d",&x),sum+=x,p=i*M+j;
                          if ((i+j)%2) T.addedge(p<<1|1,e,x);
                                 else  T.addedge(s,p<<1|1,x); 
                   }                 
                printf("Case %d: %d\n",cases,sum-T.MaxFlow(s,e));
      }   
      return 0;  
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: