cogs746 [网络流24题]骑士共存

来源:互联网 发布:56式军装淘宝 编辑:程序博客网 时间:2024/05/20 00:36

最小割 用割来表示互斥的关系
我们可以发现一个性质 就是马只能由黑格跳到白格
那么我们对图进行黑白染色(第一次写还写错了)
然后黑色点向能到达的白色点连边 障碍不进行建图
那么最后的答案就是n-m再减去最小割

#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int N=205*3,M=10*N*N,S=N*N-1,T=N*N-2,INF=1e9,DX[]={1,1,2,2,-1,-1,-2,-2},DY[]={2,-2,1,-1,2,-2,1,-1};int n=0,m=0;int b[N][N],color[N][N];int head[N*N],to[M],next[M],c[M],f[M],edge=0;int q[M],front=0,back=0,d[N*N];inline void addEdge(int u,int v,int ac) {    to[edge]=v,c[edge]=ac,next[edge]=head[u],head[u]=edge++;    to[edge]=u,c[edge]=0,next[edge]=head[v],head[v]=edge++;}inline int num(int i,int j) {    return j+n*(i-1);}#define X i+DX[k]#define Y j+DY[k]inline void build() {    memset(head,-1,sizeof(head));    int c0=0;    for (int i=1;i<=n;++i)        for (int j=1;j<=n;++j)            color[i][j]=(i+j)%2;    for (int i=1;i<=n;++i)         for (int j=1;j<=n;++j)             if (!b[i][j]) {                int x=num(i,j);                color[i][j]?addEdge(S,x,1):addEdge(x,T,1);                if (color[i][j])                    for (int k=0;k<8;++k)                        if (X>=1 && Y>=1 && X<=n && Y<=n && !b[X][Y])                            addEdge(x,num(X,Y),INF);            }}#undef X#undef Yinline int bfs() {    front=back=0;    memset(d,-1,sizeof(d));    q[back++]=S;    d[S]=0;    while (front<back) {        int x=q[front++];        for (int e=head[x];~e;e=next[e]) {            int v=to[e];            if (d[v]==-1 && c[e]>f[e]) {                d[v]=d[x]+1;                q[back++]=v;            }        }    }    return d[T]!=-1;}int dfs(int x,int mn) {    if (x==T || !mn)        return mn;    int flow=0;    for (int e=head[x];~e;e=next[e]) {        int v=to[e];        if (d[v]==d[x]+1 && c[e]>f[e]) {            int f0=dfs(v,min(mn,c[e]-f[e]));            flow+=f0;            mn-=f0;            f[e]+=f0;            f[e^1]-=f0;            if (!mn)                return flow;        }    }    if (mn)        d[x]=-1;    return flow;}inline int dinic() {    int flow=0;    while (bfs())         flow+=dfs(S,INF);    return flow;    }int main(void) {    freopen("knight.in","r",stdin);    freopen("knight.out","w",stdout);    scanf("%d%d",&n,&m);    for (int i=1;i<=m;++i) {        int x=0,y=0;        scanf("%d%d",&x,&y);        b[x][y]=1;    }       build();    printf("%d\n",n*n-m-dinic());    fclose(stdin);    fclose(stdout);    return 0;}

好菜啊 模板有个地方写错了 还是学长davidxu帮我发现的 QAQQQQ

0 0
原创粉丝点击