解题: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
原文地址:https://www.cnblogs.com/ydnhaha/p/10046737.html