BZOJ 3175 最大独立集

思路:
最大独立集嘛 用nlogn的Dinic做

//By SiriusRen
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 888888
int n,re[205][205],cnt,first[40050],next[N],v[N],w[N],vis[40050],tot,T,jy,ans;
char a[205][205],xx[]={1,-1,2,-2,1,-1,2,-2},yy[]={2,-2,1,-1,-2,2,-1,1};
void Add(int x,int y,int z){w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}
void add(int x,int y,int z){Add(x,y,z),Add(y,x,0);}
bool tell(){
    memset(vis,-1,sizeof(vis)),vis[0]=0;
    queue<int>q;q.push(0);
    while(!q.empty()){
        int t=q.front();q.pop();
        for(int i=first[t];~i;i=next[i])
            if(!~vis[v[i]]&&w[i])
                vis[v[i]]=vis[t]+1,q.push(v[i]);
    }return ~vis[T];
}
int zeng(int x,int y){
    if(x==T)return y;
    int r=0;
    for(int i=first[x];~i&&y>r;i=next[i])
        if(vis[v[i]]==vis[x]+1&&w[i]){
            int t=zeng(v[i],min(y-r,w[i]));
            w[i]-=t,w[i^1]+=t,r+=t;
        }
    if(!r)vis[x]=-1;
    return r;
}
int main(){
    memset(first,-1,sizeof(first));
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",a[i]+1);
        for(int j=1;j<=n;j++){
            a[i][j]-='0';
            if(!a[i][j])re[i][j]=++cnt;
        }
    }
    T=cnt+1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)if(re[i][j]){
            if((i+j)&1){
                add(0,re[i][j],1);
                for(int k=0;k<8;k++){
                    int dx=i+xx[k],dy=j+yy[k];
                    if(dx>=1&&dy>=1&&re[dx][dy])
                        add(re[i][j],re[dx][dy],1);
                }
            }
            else{
                add(re[i][j],T,1);
                for(int k=0;k<8;k++){
                    int dx=i+xx[k],dy=j+yy[k];
                    if(dx>=1&&dy>=1&&re[dx][dy])
                        add(re[dx][dy],re[i][j],1);
                }
            }
        }
    while(tell())while(jy=zeng(0,0x3fffffff))ans+=jy;
    printf("%d
",cnt-ans);
}

这里写图片描述

原文地址:https://www.cnblogs.com/SiriusRen/p/6532072.html