【codevs1922】[网络流24题]骑士共存问题

来源:互联网 发布:访问通用顶级域名 编辑:程序博客网 时间:2024/05/17 03:51

很轻松可以看出是割,然后由于马走路的性质,可以黑白染色转化成二分图,跟方格取数一样做
由源点向黑点引边
由黑点向能跳到的点引边
由白点向汇点引边
直接求割

#include<iostream>  #include<cstdio>  #include<cstring>  #include<algorithm>  #include<queue>  using namespace std;  int n,m,a[203][203],point[800007],tot=-1;  int num[800007],deep[800007],cur[800007],laste[800007];  int next[2000007],v[2000007],remain[2000007];  int x[10]={1,1,2,2,-1,-1,-2,-2},y[10]={2,-2,1,-1,2,-2,1,-1};  const int inf=1e9;  void add(int x,int y,int z)  {    tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z;    tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;  }  int addflow(int s,int t)  {    int minn=inf;int now=t;    while(now!=s)     {      minn=min(minn,remain[laste[now]]);      now=v[laste[now]^1];     }    now=t;    while(now!=s)     {      remain[laste[now]]-=minn;      remain[laste[now]^1]+=minn;      now=v[laste[now]^1];     }    return minn;  }  void bfs(int s,int t)  {    for (int i=s;i<=t;i++)  deep[i]=t;    deep[t]=0; queue<int> p; p.push(t);    while(!p.empty())     {      int now=p.front(); p.pop();      for (int i=point[now];i!=-1;i=next[i])      if (deep[v[i]]==t&&remain[i^1])       deep[v[i]]=deep[now]+1,p.push(v[i]);     }  }  int  isap(int s,int t)  {  int ans=0,now=s;  bfs(s,t);  for (int i=s;i<=t;i++) num[deep[i]]++;  for (int i=s;i<=t;i++) cur[i]=point[i];  while(deep[s]<t)  {  if (now==t)  {  ans+=addflow(s,t);  now=s;  }  bool p=false;  for (int i=cur[now];i!=-1;i=next[i])  {  if (deep[v[i]]+1==deep[now]&&remain[i])  {  laste[v[i]]=i;  cur[now]=i;  p=true;  now=v[i];  break;  }  }  if (!p)  {  int minn=t-1;  for (int i=point[now];i!=-1;i=next[i])  if (remain[i]) minn=min(minn,deep[v[i]]);  if (!--num[deep[now]]) break;  num[deep[now]=minn+1]++;  cur[now]=point[now];  if (now!=s) now=v[laste[now]^1];  }  }  return ans;  }  int main()  {    memset(next,-1,sizeof(next));    memset(point,-1,sizeof(point));    scanf("%d%d",&n,&m);    for (int i=1;i<=m;i++)     {      int x,y; scanf("%d%d",&x,&y);      a[x][y]=1;     }    int num=n*n+1;    for (int i=1;i<=n;i++)     if (i%2==1)      {      for (int j=1;j<=n;j++)      if (!a[i][j])      if (j%2==1)       {        int t=(i-1)*n+j;        add(0,t,1);         for (int k=0;k<8;k++)  {  int xx=i+x[k]; int yy=j+y[k];  if (xx>0&&xx<=n&&yy>0&&yy<=n&&!a[xx][yy])  add(t,(i+x[k]-1)*n+j+y[k],inf);  }        }      else  add((i-1)*n+j,num,1);      }     else      {        for (int j=1;j<=n;j++)      if (!a[i][j])      if (j%2==0)       {        int t=(i-1)*n+j;        add(0,t,1);         for (int k=0;k<8;k++)  {  int xx=i+x[k]; int yy=j+y[k];  if (xx>0&&xx<=n&&yy>0&&yy<=n&&!a[xx][yy])  add(t,(i+x[k]-1)*n+j+y[k],inf);  }        }      else  add((i-1)*n+j,num,1);      }    printf("%d",n*n-isap(0,num)-m);  }   
0 0