解题:SCOI 2007 蜥蜴

题面

拆点跑最大流

所有能跑出去的点连向汇点,容量为inf

原点连向所有初始有蜥蜴的点,容量为1

每根柱子拆成两个点“入口”和“出口”,入口向出口连容量为高度的边,出口向别的有高度的柱子的入口连容量为高度的边

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=1000,M=100000,inf=1e9;
 7 int n,m,d,f,b,s,t,t1,t2,t3,cnt,tot,ans;
 8 int p[N],pp[N],dep[N],que[N],idx[N][N];
 9 int noww[M],goal[M],flow[M];
10 char mapp[N][N]; 
11 void Link(int f,int t,int v)
12 {
13     noww[++cnt]=p[f],p[f]=cnt;
14     goal[cnt]=t,flow[cnt]=v;
15     noww[++cnt]=p[t],p[t]=cnt;
16     goal[cnt]=f,flow[cnt]=0;
17 }
18 int Dis(int a,int b,int c,int d)
19 {
20     return (a-c)*(a-c)+(b-d)*(b-d);
21 }
22 void Init(int st,int ed)
23 {
24     for(int i=1;i<=ed;i++) 
25         pp[i]=p[i],dep[i]=-1;
26     dep[st]=0,que[f=b=0]=st;
27 }
28 bool Layering(int st,int ed)
29 {
30     Init(st,ed);
31     while(f<=b)
32     {
33         int tn=que[f++];
34         for(int i=pp[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 int Dinic_Maxflow(int st,int ed)
58 {
59     int ret=0;
60     while(Layering(st,ed))
61         ret+=Augmenting(st,ed,inf);
62     return ret;
63 }
64 int main ()
65 {
66     scanf("%d%d%d",&n,&m,&d);
67     s=2*n*m+1,t=s+1,cnt=1;
68     for(int i=1;i<=n;i++)
69     {
70         scanf("%s",mapp[i]+1);
71         for(int j=1;j<=m;j++)
72             idx[i][j]=++tot;
73     }
74     for(int i=1;i<=n;i++)
75         for(int j=1;j<=m;j++)
76             if(mapp[i][j]!='0')
77             {
78                 Link(idx[i][j],idx[i][j]+n*m,mapp[i][j]-'0');
79                 if(i-d<1||i+d>n||j-d<1||j+d>m) 
80                     Link(idx[i][j]+n*m,t,inf);
81                 else
82                     for(int k=1;k<=n;k++)    
83                         for(int h=1;h<=m;h++)
84                             if(Dis(i,j,k,h)<=d*d&&(i!=k||j!=h)&&mapp[k][h]!='0')
85                                 Link(idx[i][j]+n*m,idx[k][h],mapp[i][j]-'0');
86             }
87     for(int i=1;i<=n;i++)
88     {
89         scanf("%s",mapp[i]+1);
90         for(int j=1;j<=m;j++)
91             if(mapp[i][j]=='L') ans++,Link(s,idx[i][j],1);
92     }
93     printf("%d
",ans-Dinic_Maxflow(s,t));
94     return 0;
95 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/10291784.html