bzoj1066: [SCOI2007]蜥蜴(最大流)
1066: [SCOI2007]蜥蜴
题目:传送门
题解:
哇QTT大佬一眼秒算法...ORT
其实很容易就可以看出来是一道最大流
因为有边的使用限制,那么就可以直接当成是流量来处理嘛
因为是对点进行操作,那么就可以拆点啊
一开始现将有柱子的点自己把限制条件连上,就是对点x拆成x1和x2那么就x1-->x2流量为限制
然后就是无脑乱连,对于判断是否出了边界一开始还傻逼逼的没想出来。。。
枚举多一圈界外的点,那么如果算曼哈顿距离(据说欧几里得也OK)符合条件,就判断是不是在界内:
在界内就直接连嘛,对于点x和点y,x2-->y1流量无限
在界外那就很nice,直接向ed连无限流量。
最后就是对于每个蜥蜴的操作了,直接st连蜥蜴流量为1(因为柱子上只可能有一只)
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define inf 999999999 7 using namespace std; 8 struct node 9 { 10 int x,y,c,next,other; 11 }a[1110000];int len,last[11000]; 12 void ins(int x,int y,int c) 13 { 14 int k1,k2; 15 k1=++len; 16 a[len].x=x;a[len].y=y;a[len].c=c; 17 a[len].next=last[x];last[x]=len; 18 19 k2=++len; 20 a[len].x=y;a[len].y=x;a[len].c=0; 21 a[len].next=last[y];last[y]=len; 22 23 a[k1].other=k2; 24 a[k2].other=k1; 25 } 26 int n,m,D,head,tail,st,ed; 27 int list[11000],h[111000]; 28 bool bt_h() 29 { 30 memset(h,0,sizeof(h));h[st]=1; 31 list[1]=st;head=1;tail=2; 32 while(head!=tail) 33 { 34 int x=list[head]; 35 for(int k=last[x];k;k=a[k].next) 36 { 37 int y=a[k].y; 38 if(h[y]==0 && a[k].c>0) 39 { 40 h[y]=h[x]+1; 41 list[tail++]=y; 42 } 43 } 44 head++; 45 } 46 if(h[ed]>0)return true; 47 return false; 48 } 49 int find_flow(int x,int flow) 50 { 51 if(x==ed)return flow; 52 int s=0,t; 53 for(int k=last[x];k;k=a[k].next) 54 { 55 int y=a[k].y; 56 if(h[y]==h[x]+1 && a[k].c>0 && s<flow) 57 { 58 s+=t=find_flow(y,min(a[k].c,flow-s)); 59 a[k].c-=t;a[a[k].other].c+=t; 60 } 61 } 62 if(s==0)h[x]=0; 63 return s; 64 } 65 char A[66][66],B[66][66]; 66 int d[66][66]; 67 int main() 68 { 69 scanf("%d%d%d",&n,&m,&D);int ss=0; 70 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)d[i][j]=++ss; 71 for(int i=1;i<=n;i++)scanf("%s",A[i]+1); 72 for(int i=1;i<=n;i++)scanf("%s",B[i]+1); 73 len=0;memset(last,0,sizeof(last)); 74 st=2*n*m+1,ed=st+1; 75 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(A[i][j]!='0')ins(d[i][j],d[i][j]+n*m,A[i][j]-'0'); 76 for(int i=1;i<=n;i++) 77 for(int j=1;j<=m;j++) 78 if(A[i][j]!='0') 79 for(int tx=0;tx<=n+1;tx++) 80 for(int ty=0;ty<=m+1;ty++) 81 if(abs(i-tx)+abs(j-ty)<=D) 82 if(tx>=1 && tx<=n && ty>=1 && ty<=m)ins(d[i][j]+n*m,d[tx][ty],inf); 83 else ins(d[i][j]+n*m,ed,inf); 84 int sum=0; 85 for(int i=1;i<=n;i++) 86 for(int j=1;j<=m;j++) 87 if(B[i][j]=='L') 88 ins(st,d[i][j],1),sum++; 89 int ans=0; 90 while(bt_h())ans+=find_flow(st,inf); 91 printf("%d\n",sum-ans); 92 return 0; 93 }