码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-08-06 23:04:52      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:io   for   ar   amp   size   ad   har   ef   

/*刚开始不会写,最大点权独立集神马都不知道,在潘神的指导下终于做出来,灰常感谢ps;
和方格取数差不多奇偶建图,对于D必割点权为0,对于.必然不割点权为inf。然后和方格取数差不多的建图
.--.||E权值为2,,.||E--D权值为0.
最大点权独立集=sum-最小点权覆盖。
*/
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define inf 0x3fffffff
#define ii 50
#define N   3000
struct node {
 int u,v,w,next;
}bian[N*6];
int head[N],yong,s,t,dis[N];
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,T,id[ii][ii],cnt,sum,f=0;
    char ss[ii][ii];
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        cnt=1;sum=0;
        init();
        for(i=1;i<=n;i++) {
            scanf("%s",ss[i]+1);
            for(j=1;j<=m;j++) {
                if(ss[i][j]=='.'||ss[i][j]=='E')//记录总数
                    sum+=4;
                id[i][j]=cnt++;
            }
        }
        s=0;t=n*m+1;
        for(i=1;i<=n;i++)
        for(j=1;j<=m;j++) {
            if((i+j)&1) {//奇偶建图与源点相连
                if(ss[i][j]=='.')
                    add(s,id[i][j],inf);//必然不割
                if(ss[i][j]=='D')//必割
                    add(s,id[i][j],0);
                if(ss[i][j]=='E')//任意选择
                    add(s,id[i][j],4);
                if(i>=2) {
                    if(ss[i][j]=='.'||ss[i][j]=='E') {
                        if(ss[i-1][j]=='.'||ss[i-1][j]=='E')add(id[i][j],id[i-1][j],2);//
                        if(ss[i-1][j]=='D')add(id[i][j],id[i-1][j],0);//
                    }
                    else
                        add(id[i][j],id[i-1][j],0);
                }
                if(j>=2) {
                   if(ss[i][j]=='.'||ss[i][j]=='E') {
                        if(ss[i][j-1]=='.'||ss[i][j-1]=='E')add(id[i][j],id[i][j-1],2);
                        if(ss[i][j-1]=='D')add(id[i][j],id[i][j-1],0);
                    }
                    else
                        add(id[i][j],id[i][j-1],0);
                }
                if(i<=n-1){
                     if(ss[i][j]=='.'||ss[i][j]=='E') {
                        if(ss[i+1][j]=='.'||ss[i+1][j]=='E')add(id[i][j],id[i+1][j],2);
                        if(ss[i+1][j]=='D')add(id[i][j],id[i+1][j],0);
                    }
                    else
                        add(id[i][j],id[i+1][j],0);
                }
                if(j<=m-1) {
                      if(ss[i][j]=='.'||ss[i][j]=='E') {
                        if(ss[i][j+1]=='.'||ss[i][j+1]=='E')add(id[i][j],id[i][j+1],2);
                        if(ss[i][j+1]=='D')add(id[i][j],id[i][j+1],0);
                        }
                    else
                        add(id[i][j],id[i][j+1],0);
                }
            }
            else {//与汇点相连
                if(ss[i][j]=='.')
                    add(id[i][j],t,inf);
                if(ss[i][j]=='E')
                    add(id[i][j],t,4);
                if(ss[i][j]=='D')
                    add(id[i][j],t,0);
            }
        }
        printf("Case %d: ",++f);
        printf("%d\n",sum-ISAP());
    }
return 0;
}

hdu 4859 最大点权独立集的变形(方格取数的变形),布布扣,bubuko.com

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

标签:io   for   ar   amp   size   ad   har   ef   

原文地址:http://blog.csdn.net/u011483306/article/details/38406677

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!