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

来源:互联网 发布:小米生活和淘宝的关系 编辑:程序博客网 时间:2024/06/10 06:24
/*分奇偶为二部图,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 60struct 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\n",sum-ISAP());   }return 0;}

0 0
原创粉丝点击