• 解题:BZOJ 4808 马


    题面

    以前写过的题,翻出来学习网络流写二分图匹配,因为复杂度更优秀,$Dinic$是$O(sqrt(n)m)$哒~

    原点向左部点连流量为$1$的边,左部点向对应右部点连流量为$1$的边,右部点向汇点连流量为$1$的边,然后跑

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int B=205,N=40005,M=320005,inf=1e9;
     6 const int mov[8][2]={{2,1},{2,-1},{-2,1},{-2,-1},{1,2},{1,-2},{-1,2},{-1,-2}};
     7 int T,n,m,s,t,f,b,t1,t2,rd,num,cnt,tot,ans;
     8 int noww[2*M],goal[2*M],flow[2*M];
     9 int p[N],pp[N],dep[N],que[N];
    10 int bro[B][B],mapp[B][B];
    11 int tonum(int x,int y)
    12 {
    13     return (x-1)*m+y;
    14 }
    15 bool check(int x,int y)
    16 {
    17     return x>=1&&x<=n&&y>=1&&y<=m; 
    18 }
    19 void link(int f,int t,int v)
    20 {
    21     noww[++cnt]=p[f],p[f]=cnt;
    22     goal[cnt]=t,flow[cnt]=v;
    23     noww[++cnt]=p[t],p[t]=cnt;
    24     goal[cnt]=f,flow[cnt]=0;
    25 }
    26 bool Layering(int st,int ed)
    27 {
    28     for(int i=1;i<=num;i++) pp[i]=p[i];
    29     memset(dep,-1,sizeof dep);
    30     dep[st]=0,que[f=b=0]=st;
    31     while(f<=b)
    32     {
    33         int tn=que[f++];
    34         for(int i=p[tn];i;i=noww[i])
    35             if(dep[goal[i]]==-1&&flow[i])
    36                 dep[goal[i]]=dep[tn]+1,que[++b]=goal[i];
    37     }
    38     return ~dep[ed];
    39 }
    40 int Augmenting(int nd,int ed,int mn)
    41 {
    42     if(nd==ed||!mn) return mn;
    43     int tmp=0,tep=0;
    44     for(int i=pp[nd];i;i=noww[i])
    45     {
    46         pp[nd]=i;
    47         if(dep[goal[i]]==dep[nd]+1)
    48             if(tep=Augmenting(goal[i],ed,min(mn,flow[i])))
    49             {
    50                 flow[i]-=tep,mn-=tep;
    51                 flow[i^1]+=tep,tmp+=tep;
    52                 if(!mn) break;
    53             }
    54     }
    55     return tmp;
    56 }
    57 void Dinic_Maxflow(int st,int ed)
    58 {
    59     while(Layering(st,ed))
    60         ans+=Augmenting(st,ed,inf);
    61 }
    62 int main ()
    63 {
    64     scanf("%d%d",&n,&m);
    65     cnt=1,num=n*m+2,tot=n*m,s=n*m+1,t=n*m+2;
    66     for(int i=1;i<=n;i++)
    67         for(int j=1;j<=m;j++)
    68         {
    69             scanf("%d",&rd);
    70             bro[i][j]=rd,tot-=rd;
    71         }
    72     for(int i=1;i<=n;i++)
    73         for(int j=1;j<=m;j++)
    74             if(!bro[i][j]) 
    75             {
    76                 if((i^j)&1)
    77                 {
    78                     link(s,tonum(i,j),1);
    79                     for(int k=0;k<8;k++)
    80                     {
    81                         t1=i+mov[k][0],t2=j+mov[k][1];
    82                         if(check(t1,t2)&&!bro[t1][t2]) 
    83                             link(tonum(i,j),tonum(t1,t2),1);
    84                     }
    85                 }
    86                 else link(tonum(i,j),t,1);
    87             }
    88     Dinic_Maxflow(s,t);
    89     printf("%d",tot-ans);
    90     return 0;
    91 }
    92 
    View Code
  • 相关阅读:
    windows下 CodeBlock13-12 实验 C++11 测试
    用矩阵运算实现最小二乘法曲线拟合算法
    winXP 系统下ubuntu-12.04 硬盘安装
    TCP服务器并发编程构架:完成端口IOCP模式
    TCP服务器并发编程构架:完成例程IRP模式
    续:双缓存队列_模板类
    双缓存静态循环队列(三)
    如何在只知道SQL_ID时,查询到此sql语句的执行计算机名称(是两三天前的SQL语句)
    RMAN Catalog 和 Nocatalog 的区别
    异机恢复后ORA-01152错误解决
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10046737.html
Copyright © 2020-2023  润新知