HDU2732 Leapin' Lizards 最大流

题目

题意:

t组输入,然后地图有n行m列,且n,m<=20.有一个最大跳跃距离d。后面输入一个n行的地图,每一个位置有一个值,代表这个位置的柱子可以经过多少个猴子。之后再输入一个地图'L'代表这个位置刚开始有一个猴子.'.'代表这个位置刚开始没有猴子

题解:

  1 //其实这道题就是建图比较麻烦,其他还是可以的。但是最大的坑点就是
  2 //1、输出的时候的单复数,没有逃出来的猴子数为0、1的时候,要输出lizard和was,否则要输出lizards和were。我也是醉了
  3 //2、他那个条约最大距离是曼哈顿距离——d(i,j)=|X1-X2|+|Y1-Y2|.
  4 
  5 //建图的话。。st是图的起始点,en是图的终止点
  6 //首先要拆点,一个点要拆成两个点i->start和i->last。容量为这个点的承受人数
  7 //如果一个点可以向上、下、左、右移动直接跳出这个图,那他就成功逃生。就让这个i->last和en连一条容量INF的边
  8 //如果一个点它上面原来有猴子(地图上是‘L’),那么就要让起点st和这一个点的i->start相连一条容量为1的边
  9 //如果一个点的曼哈顿距离小于规定距离,就要让i->last和j->start连一条容量INF(无穷大)边.还要建
 10 //j->last和i->start连一条边,因为两个点可以互相往来
 11 //
 12 //同时每建一条正向边,还需要建一条容量为0的反向边
 13 #include<stdio.h>
 14 #include<string.h>
 15 #include<iostream>
 16 #include<algorithm>
 17 #include<queue>
 18 #include<math.h>
 19 #include<stdlib.h>
 20 using namespace std;
 21 const int maxn=100000;
 22 const int INF=0x3f3f3f3f;
 23 int head[maxn],cnt,st,en,dis[maxn],cur[maxn];
 24 struct shudui
 25 {
 26     int x,y,z;
 27 }m[405];
 28 struct edge
 29 {
 30     int v,next,c,flow;
 31 } e[maxn];
 32 void add_edge(int x,int y,int z)
 33 {
 34     e[cnt].v=y;
 35     e[cnt].c=z;
 36     e[cnt].flow=0;
 37     e[cnt].next=head[x];
 38     head[x]=cnt++;
 39 }
 40 bool bfs()
 41 {
 42     memset(dis,0,sizeof(dis));
 43     dis[st]=1;
 44     queue<int>r;
 45     r.push(st);
 46     while(!r.empty())
 47     {
 48         int x=r.front();
 49         r.pop();
 50         for(int i=head[x]; i!=-1; i=e[i].next)
 51         {
 52             int v=e[i].v;
 53             if(!dis[v] && e[i].c>e[i].flow)
 54             {
 55                 dis[v]=dis[x]+1;
 56                 r.push(v);
 57             }
 58         }
 59     }
 60     return dis[en];
 61 }
 62 int dinic(int s,int limit)
 63 {
 64     if(s==en || !limit) return limit;
 65     int ans=0;
 66     for(int &i=cur[s]; i!=-1; i=e[i].next)
 67     {
 68         int v=e[i].v,feed;
 69         if(dis[v]!=dis[s]+1) continue;
 70         feed=dinic(v,min(limit,e[i].c-e[i].flow));
 71         if(feed)
 72         {
 73             e[i].flow+=feed;
 74             e[i^1].flow-=feed;
 75             limit-=feed;
 76             ans+=feed;
 77             if(limit==0) break;
 78         }
 79     }
 80     if(!ans) dis[s]=-1;
 81     return ans;
 82 }
 83 int main()
 84 {
 85 
 86     int t,p=0;
 87     char s[25][25];
 88     int w[25][25];
 89     scanf("%d",&t);
 90     while(t--)
 91     {
 92         int sum=0;
 93         memset(w,0,sizeof(w));
 94         memset(head,-1,sizeof(head));
 95         cnt=0;
 96         int n,d;
 97         scanf("%d%d",&n,&d);
 98         for(int i=1; i<=n; ++i)
 99         {
100             scanf("%s",s[i]+1);
101         }
102         int len=strlen(s[1]+1),number=0;
103         for(int i=1;i<=n;++i)
104         {
105             for(int j=1;j<=len;++j)
106             {
107                 if(s[i][j]!='0')
108                 {
109                     m[++number].x=i;
110                     m[number].y=j;
111                     m[number].z=s[i][j]-'0';
112                 }
113             }
114         }
115         st=0;
116         en=2*number+1;
117         for(int i=1;i<=n;++i)
118         {
119             scanf("%s",s[i]+1);
120         }
121         for(int i=1;i<=n;++i)
122         {
123             for(int j=1;j<=len;++j)
124             {
125                 if(s[i][j]=='L')
126                 {
127                     sum++;
128                     w[i][j]=1;
129                 }
130             }
131         }
132         for(int i=1;i<=number;++i)
133         {
134             add_edge(i,i+number,m[i].z);
135             add_edge(i+number,i,0);
136             int x=m[i].x;
137             int y=m[i].y;
138             if(y<=d || y>len-d || x<=d || x>n-d)
139             {
140                 add_edge(i+number,en,INF);
141                 add_edge(en,i+number,0);
142             }
143             if(w[x][y])
144             {
145                 add_edge(st,i,1);
146                 add_edge(i,st,0);
147             }
148             for(int j=i+1;j<=number;++j)
149             {
150                 int xx=m[j].x;
151                 int yy=m[j].y;
152                 int dist=abs(xx-x)+abs(yy-y);
153                 if(dist<=d)
154                 {
155                     add_edge(i+number,j,INF);  //这里还是要建双向边
156                     add_edge(j,i+number,0);
157                     add_edge(j+number,i,INF);
158                     add_edge(i,j+number,0);
159                 }
160             }
161         }
162 
163         int ans=0;
164         while(bfs())
165         {
166             for(int i=0; i<=en; i++)
167                 cur[i]=head[i];
168             ans+=dinic(st,1);
169         }
170 //        if(sum-ans!=0)
171 //        {
172 //            if(sum-ans!=1)
173 //            printf("Case #%d: %d lizards were left behind.
",++p,sum-ans);
174 //            else printf("Case #%d: %d lizard were left behind.
",++p,sum-ans);
175 //        }
176 //        else printf("Case #%d: no lizard was left behind.
",++p);
177 //我原来这一部分的判断是像注释部分一样,原本我以为我已经绕过了单复数lizard(s),没想到我还是掉坑里了
178 //后面的were和was也是要改的,我。。。。。。难受
179         int left=sum-ans;
180         if(left==0)
181             printf("Case #%d: no lizard was left behind.
",++p);
182         else if(left==1)
183             printf("Case #%d: 1 lizard was left behind.
",++p);
184         else printf("Case #%d: %d lizards were left behind.
",++p,left);
185     }
186     return 0;
187 }
原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11781487.html