• 网络流24题之骑士共存问题


    乍一看与那个互不侵犯King很像,但这个数据范围就只能网络流了

    我们可以发现只有黑的能攻击白的,白的能攻击黑的。

    所以黑白相当于一个二分图

    最小点独立集=总数-最小割(也就是说两个点里要至少留一个)

    最小割=最小点覆盖=最大匹配

    网络流建图求最大匹配即可

    同时在做这题的过程中我发现对于网络流求最大匹配如果你一开始就能明确二分图的区分那么你可以建s->i,i->i~->i~->j,j->j~,j~->t

    如果你并不能将他们区分开那么就要建s->i,i->j~,j~->t这种模型

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=2005;
     4 int head[N*N*2],d[N*N*2],ma[N][N];
     5 int n,m,cnt=-1,s,t;
     6 struct node{
     7     int to,nex,w;
     8 }e[2000005];
     9 int xx[8]={-1,-2,-1,-2,2,2,1,1};
    10 int yy[8]={2,1,-2,-1,-1,1,-2,2};
    11 void add(int x,int y,int w)
    12 {
    13     e[++cnt].to=y;e[cnt].nex=head[x];head[x]=cnt;e[cnt].w=w;
    14     e[++cnt].to=x;e[cnt].nex=head[y];head[y]=cnt;e[cnt].w=0;
    15 }
    16 queue<int>q;
    17 bool bfs(int x,int y)
    18 {
    19     memset(d,-1,sizeof(d));
    20     d[x]=0;q.push(x);
    21     while(!q.empty())
    22     {
    23         int x=q.front();q.pop();
    24         for(int i=head[x];i!=-1;i=e[i].nex)
    25         {
    26             int y=e[i].to;
    27             if(d[y]!=-1||!e[i].w)continue;
    28             d[y]=d[x]+1;q.push(y);
    29         }
    30     }
    31     return d[y]!=-1;
    32 }
    33 int dfs(int x,int w,int yy)
    34 {
    35     if(x==yy||!w)return w;
    36     int s=0;
    37     for(int i=head[x];i!=-1;i=e[i].nex)
    38     {
    39         int y=e[i].to;
    40         if(!e[i].w||d[y]!=d[x]+1)continue;
    41         int flow=dfs(y,min(w-s,e[i].w),yy);
    42         if(!flow){
    43             d[y]=-1;continue;
    44         }
    45         e[i].w-=flow;e[i^1].w+=flow;s+=flow;
    46         if(s==w)return s;
    47     }
    48     return s;
    49 }
    50 int dinic()
    51 {
    52     int ans=0;
    53     while(bfs(s,t))
    54     {
    55         ans+=dfs(s,1e9,t);
    56     }
    57     return ans;
    58 }
    59 int main()
    60 {
    61     int n,m;int tot=0;
    62     scanf("%d%d",&n,&m);
    63     memset(head,-1,sizeof(head));
    64     for(int i=1;i<=n;++i)
    65         for(int j=1;j<=n;++j)
    66         ma[i][j]=++tot;
    67     for(int i=1;i<=m;++i)
    68     {
    69         int x,y;
    70         scanf("%d%d",&x,&y);
    71         ma[x][y]=0;
    72     }
    73     s=0;t=n*n*2+1;int p=n*n;
    74     for(int i=1;i<=n;++i)
    75         for(int j=(i%2)?1:2;j<=n;j+=2)
    76         {
    77             if(ma[i][j])
    78             {
    79                 add(s,ma[i][j],1);
    80                 for(int k=0;k<8;++k)
    81                 {
    82                     int nx=i+xx[k];int ny=j+yy[k];
    83                     if((nx<1||nx>n||ny<1||ny>n)||ma[nx][ny]==0)continue;
    84                     add(ma[i][j],ma[nx][ny]+p,1);
    85                 }
    86             }
    87         }
    88     for(int i=1;i<=n;++i)
    89         for(int j=(i%2)?2:1;j<=n;j+=2)
    90         if(ma[i][j])
    91         add(ma[i][j]+p,t,1);
    92     int ans=dinic();
    93     printf("%d
    ",n*n-m-ans);
    94     return 0; 
    95 }
  • 相关阅读:
    二手房交易平台需求分析心得——字节移动小组
    结对编程之个人项目代码分析
    五月最新版 重装win10软件
    学习必备的——超级有用的网站!!!
    SQL中sa被禁用
    19 erp沙盘校赛
    temp
    Bootstrap 学习日志(二)
    Bootstrap 学习日志(一)
    关于Android上进行模拟登陆时的验证码问题
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8397277.html
Copyright © 2020-2023  润新知