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 }

 

posted @ 2018-03-26 20:42  CHerish_OI  阅读(162)  评论(0编辑  收藏  举报