[SCOI2007]蜥蜴(最大流)
最大流的入门题,比纯网络流的模板多了一个建模的过程。
首先建出源点并向所有的有蜥蜴的点建边(S,u,1),
之后把能互相到达的点建边,这里考虑一下容量改为多少,a[i][j]吗?
如果这样那么加入这个点(i,j)可以到达多个点该怎么办呢?
所以要拆点!把一个点拆成入点u和出点v,连边(u,v,a[i][j])即可。
接下来把所有能escape的点向汇点连边,最后跑最大流即可。
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 const int N=250,INF=1e15; 5 int sum,ans,tot=1,S,T,cnt,n,m,D,b[N][N],d[N*N],a[N][N],ma[N][N],head[N*N],to[N*N*100],ne[N*N*100],w[N*N*100]; 6 char ch[N]; 7 void add(int x,int y,int z) 8 { 9 to[++tot]=y; 10 w[tot]=z; 11 ne[tot]=head[x]; 12 head[x]=tot; 13 } 14 int dis(int x,int y,int l,int r) 15 { 16 return (x-l)*(x-l)+(y-r)*(y-r); 17 } 18 bool escape(int i,int j) 19 { 20 if(dis(i,j,i,0)<=D) return true; 21 if(dis(i,j,i,m+1)<=D) return true; 22 if(dis(i,j,0,j)<=D) return true; 23 if(dis(i,j,n+1,j)<=D) return true; 24 return false; 25 } 26 bool bfs(int x) 27 { 28 memset(d,0,sizeof(d)); 29 queue<int>q; 30 q.push(x); 31 d[x]=1; 32 while(q.size()) 33 { 34 int y=q.front(); 35 q.pop(); 36 for(int i=head[y];i;i=ne[i]) 37 { 38 int z=to[i]; 39 if(!w[i]||d[z]) continue; 40 d[z]=d[y]+1; 41 if(z==T) return true; 42 q.push(z); 43 } 44 } 45 return false; 46 } 47 int dfs(int x,int in) 48 { 49 if(x==T) return in; 50 int out=0; 51 for(int i=head[x];i;i=ne[i]) 52 { 53 int y=to[i]; 54 if(d[y]!=d[x]+1||!w[i]) continue; 55 int tmp=dfs(y,min(in,w[i])); 56 out+=tmp; 57 in-=tmp; 58 w[i]-=tmp; 59 w[i^1]+=tmp; 60 } 61 if(!out) d[x]=0; 62 return out; 63 } 64 signed main() 65 { 66 //freopen("1.in","r",stdin); 67 scanf("%lld%lld%lld",&n,&m,&D); 68 D=D*D; 69 cnt++; 70 for(int i=1;i<=n;i++) 71 { 72 scanf("%s",ch); 73 for(int j=1;j<=m;j++) 74 { 75 a[i][j]=ch[j-1]-'0'; 76 if(a[i][j]) 77 { 78 ma[i][j]=++cnt; 79 b[i][j]=++cnt; 80 add(ma[i][j],b[i][j],a[i][j]); 81 add(b[i][j],ma[i][j],0); 82 } 83 } 84 } 85 cnt++; 86 S=1;T=cnt; 87 for(int i=1;i<=n;i++) 88 { 89 scanf("%s",ch); 90 for(int j=0;j<m;j++) 91 { 92 if(ch[j]=='L') 93 { 94 sum++; 95 add(S,ma[i][j+1],1); 96 add(ma[i][j+1],S,0); 97 } 98 } 99 } 100 for(int i=1;i<=n;i++) 101 { 102 for(int j=1;j<=m;j++) 103 { 104 if(!a[i][j]) continue; 105 for(int l=1;l<=n;l++) 106 { 107 for(int r=1;r<=m;r++) 108 { 109 if(!a[l][r]||dis(i,j,l,r)>D) continue; 110 add(b[i][j],ma[l][r],INF); 111 add(ma[l][r],b[i][j],0); 112 } 113 } 114 } 115 } 116 for(int i=1;i<=n;i++) 117 { 118 for(int j=1;j<=m;j++) 119 { 120 if(!a[i][j]||!escape(i,j)) continue; 121 add(b[i][j],T,INF); 122 add(T,b[i][j],0); 123 } 124 } 125 while(bfs(S)) 126 { 127 ans+=dfs(S,INF); 128 } 129 printf("%lld",sum-ans); 130 return 0; 131 }