hdu 3657最大点权独立集变形(方格取数变形)

/*
分奇偶为二部图,s与奇建图,t与偶建图,权值为当前数的值,如果遇到必取的权值置为inf。
奇偶建边为相邻的权值为2*(x&y);所有数的值-最小点全覆盖。
置为inf意为不能割掉。奇偶边权意为可以割掉相邻的。
*/
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define inf 0x3fffffff
#define N 2600
#define ii 60
struct node {
int u,v,w,next;
}bian[N*4*2];
int head[N],yong,s,t,dis[N],ma[ii][ii],id[ii][ii],f[ii][ii];;
void init(){
yong=0;
memset(head,-1,sizeof(head));
memset(dis,-1,sizeof(dis));
}
void addedge(int u,int v,int w) {
bian[yong].u=u;
bian[yong].v=v;
bian[yong].w=w;
bian[yong].next=head[u];
head[u]=yong++;
}
void add(int u,int v,int w) {
 addedge(u,v,w);
 addedge(v,u,0);
}
void bfs() {
int u,v,i;
queue<int>q;
q.push(t);
dis[t]=0;
while(!q.empty()) {
    u=q.front();
    q.pop();
    for(i=head[u];i!=-1;i=bian[i].next) {
        v=bian[i].v;
        if(dis[v]==-1) {
            dis[v]=dis[u]+1;
            q.push(v);
        }
    }
}
return ;
}
int ISAP() {
int sum=0;
bfs();
int  gap[N],cur[N],stac[N],top,i;
memset(gap,0,sizeof(gap));
for(i=s;i<=t;i++) {
    gap[dis[i]]++;
    cur[i]=head[i];
}
int k=s;
top=0;
while(dis[s]<t+1) {
     if(k==t) {
            int minn=inf,index;
        for(i=0;i<top;i++) {
            int e=stac[i];
            if(minn>bian[e].w) {
                minn=bian[e].w;
                index=i;
            }
        }
        for(i=0;i<top;i++) {
            int e=stac[i];
            bian[e].w-=minn;
            bian[e^1].w+=minn;
        }
        sum+=minn;
        top=index;
        k=bian[stac[top]].u;
     }
     for(i=cur[k];i!=-1;i=bian[i].next) {
       int  v=bian[i].v;
        if(bian[i].w&&dis[k]==dis[v]+1) {
            cur[k]=i;
            k=v;
            stac[top++]=i;
            break;
        }
     }
     if(i==-1) {
        int m=t+1;
        for(i=head[k];i!=-1;i=bian[i].next)
            if(m>dis[bian[i].v]&&bian[i].w) {
                m=dis[bian[i].v];
                cur[k]=i;
            }
            if(--gap[dis[k]]==0)break;
            gap[dis[k]=m+1]++;
            if(k!=s)
                k=bian[stac[--top]].u;
     }
}
return sum;
}
int main() {
   int n,m,i,j,k,sum,cnt;
   while(scanf("%d%d%d",&n,&m,&k)!=EOF) {
     init();
     sum=0;
     cnt=1;
     for(i=1;i<=n;i++)
     for(j=1;j<=m;j++) {
        scanf("%d",&ma[i][j]);
        sum+=ma[i][j];
        id[i][j]=cnt++;
     }
      memset(f,0,sizeof(f));
      while(k--) {
        scanf("%d%d",&i,&j);
        f[i][j]=1;
      }
      s=0;
      t=n*m+1;
      for(i=1;i<=n;i++)
      for(j=1;j<=m;j++) {
          if((i+j)&1) {
            if(f[i][j])
                add(s,id[i][j],inf);
            else
                add(s,id[i][j],ma[i][j]);
                if(i>=2)
                    add(id[i][j],id[i-1][j],2*(ma[i][j]&ma[i-1][j]));
                if(j>=2)
                    add(id[i][j],id[i][j-1],2*(ma[i][j]&ma[i][j-1]));
                if(i<=n-1)
                    add(id[i][j],id[i+1][j],2*(ma[i][j]&ma[i+1][j]));
                if(j<=m-1)
                    add(id[i][j],id[i][j+1],2*(ma[i][j]&ma[i][j+1]));
          }
          else  {
            if(f[i][j])add(id[i][j],t,inf);
            else add(id[i][j],t,ma[i][j]);
          }
      }
      printf("%d
",sum-ISAP());
   }
return 0;
}

原文地址:https://www.cnblogs.com/thefirstfeeling/p/4410658.html