【bzoj1066】: [SCOI2007]蜥蜴 图论-最大流
把石柱拆点,流量为高度
然后S与蜥蜴连流量1的边
互相能跳到的石柱连inf的边
石柱能到边界外的和T连inf的边
然后跑dinic就好了
1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 #include <queue> 8 using namespace std; 9 const int N=1000000; 10 const int inf=1e9; 11 struct edge{ 12 int next,to,c; 13 }e[N+1]; 14 int ade=1,S=1,T=2,n,m,c,d,CNT=2; 15 int first[N+1],dis[N+1],now[N+1],mp[25][25],I[25][25],O[25][25]; 16 queue <int> Q; 17 18 void addedge(int x,int y,int cap){ 19 e[++ade].next=first[x]; 20 e[ade].to=y; 21 e[ade].c=cap; 22 first[x]=ade; 23 e[++ade].next=first[y]; 24 e[ade].to=x; 25 e[ade].c=0; 26 first[y]=ade; 27 } 28 29 #define s e[x].to 30 #define cap e[x].c 31 #define CAP e[x^1].c 32 bool bfs(){ 33 for (int i=1;i<=CNT;i++) dis[i]=inf; 34 Q.push(S); 35 dis[S]=0; 36 while (!Q.empty()){ 37 int p=Q.front(); 38 Q.pop(); 39 for (int x=first[p];x;x=e[x].next){ 40 if (dis[s]>dis[p]+1 && cap>0){ 41 Q.push(s); 42 dis[s]=dis[p]+1; 43 } 44 } 45 } 46 return dis[T]!=inf; 47 } 48 49 int dfs(int p,int mf){ 50 if (p==T) return mf; 51 for (int x=now[p];x;x=e[x].next){ 52 now[p]=x; 53 if (dis[s]==dis[p]+1 && cap>0){ 54 int f=dfs(s,min(mf,cap)); 55 if (f){ 56 cap-=f; 57 CAP+=f; 58 return f; 59 } 60 } 61 } 62 return 0; 63 } 64 #undef s 65 #undef cap 66 #undef CAP 67 68 69 int dinic(){ 70 int ans=0,f; 71 while (bfs()){ 72 for (int i=1;i<=CNT;i++) now[i]=first[i]; 73 while (f=dfs(S,inf)){ 74 ans+=f; 75 } 76 } 77 return ans; 78 } 79 80 void make_p(){ 81 for (int i=1;i<=n;i++){ 82 for (int j=1;j<=m;j++){ 83 if (mp[i][j]){ 84 addedge(I[i][j],O[i][j],mp[i][j]); 85 for (int x=i-d;x<=i+d;x++){ 86 for (int y=j-d;y<=j+d;y++){ 87 if (abs(i-x)+abs(j-y)>d) continue; 88 if (x<1 || x>n || y<1 || y>m) {addedge(O[i][j],T,inf); continue;} 89 if (mp[x][y] && (x!=i || y!=j)){addedge (O[i][j],I[x][y],inf); } 90 } 91 } 92 } 93 } 94 } 95 } 96 97 int main(){ 98 scanf("%d%d%d",&n,&m,&d); 99 for (int i=1;i<=n;i++){ 100 char s[25]; 101 scanf("%s",s+1); 102 for (int j=1;j<=m;j++){ 103 mp[i][j]=s[j]-'0'; 104 if (mp[i][j]) I[i][j]=++CNT,O[i][j]=++CNT; 105 } 106 } 107 make_p(); 108 for (int i=1;i<=n;i++){ 109 char s[25]; 110 scanf("%s",s+1); 111 for (int j=1;j<=m;j++){ 112 if (s[j]=='L'){ 113 addedge(S,I[i][j],1); 114 c++; 115 } 116 } 117 } 118 printf("%d\n",c-dinic()); 119 return 0; 120 }