HDU 2732 Leapin' Lizards(最大流)
http://acm.hdu.edu.cn/showproblem.php?pid=2732
题意:
给出n行的网格,还有若干只蜥蜴,每只蜥蜴一开始就在一个格子之中,并且给出蜥蜴每次的最大跳跃长度d。每个格子中有一个数字,代表从这个格子中最多能跳出几只蜥蜴,之后就不能有蜥蜴再跳入这个格子之中了。求出最后最少有几只蜥蜴不能跳出网格。
思路:
关键是建图。
设汇点就是跳出网格。
每个格子跳出的蜥蜴数是有限制的,那么这就很明显的是要拆点,容量为允许跳出的蜥蜴数。如果在这个格子上能跳出网格,那就将这个格子与汇点连接起来,容量为INF。如果不能的话,它可以跳到别的格子中去,所以与它距离小于等于d的格子要与之相连,容量为INF。
蜥蜴所在的格子就与源点相连,最后求得的最大流就是能跳出网格的蜥蜴的最大值。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 8 const int maxn=1000+5; 9 const int INF=0x3f3f3f3f; 10 11 12 struct Edge 13 { 14 int from,to,cap,flow; 15 Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){} 16 }; 17 18 struct Dinic 19 { 20 int n,m,s,t; 21 vector<Edge> edges; 22 vector<int> G[maxn]; 23 bool vis[maxn]; 24 int cur[maxn]; 25 int d[maxn]; 26 27 void init(int n) 28 { 29 this->n=n; 30 for(int i=0;i<n;++i) G[i].clear(); 31 edges.clear(); 32 } 33 34 void AddEdge(int from,int to,int cap) 35 { 36 edges.push_back( Edge(from,to,cap,0) ); 37 edges.push_back( Edge(to,from,0,0) ); 38 m=edges.size(); 39 G[from].push_back(m-2); 40 G[to].push_back(m-1); 41 } 42 43 bool BFS() 44 { 45 queue<int> Q; 46 memset(vis,0,sizeof(vis)); 47 vis[s]=true; 48 d[s]=0; 49 Q.push(s); 50 while(!Q.empty()) 51 { 52 int x=Q.front(); Q.pop(); 53 for(int i=0;i<G[x].size();++i) 54 { 55 Edge& e=edges[G[x][i]]; 56 if(!vis[e.to] && e.cap>e.flow) 57 { 58 vis[e.to]=true; 59 d[e.to]=d[x]+1; 60 Q.push(e.to); 61 } 62 } 63 } 64 return vis[t]; 65 } 66 67 int DFS(int x,int a) 68 { 69 if(x==t || a==0) return a; 70 int flow=0, f; 71 for(int &i=cur[x];i<G[x].size();++i) 72 { 73 Edge &e=edges[G[x][i]]; 74 if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0) 75 { 76 e.flow +=f; 77 edges[G[x][i]^1].flow -=f; 78 flow +=f; 79 a -=f; 80 if(a==0) break; 81 } 82 } 83 return flow; 84 } 85 86 int Maxflow(int s,int t) 87 { 88 this->s=s; this->t=t; 89 int flow=0; 90 while(BFS()) 91 { 92 memset(cur,0,sizeof(cur)); 93 flow +=DFS(s,INF); 94 } 95 return flow; 96 } 97 }DC; 98 99 int n,d,m; 100 int src,dst; 101 102 int main() 103 { 104 //freopen("D:\\input.txt","r",stdin); 105 int T; 106 string s; 107 scanf("%d",&T); 108 for(int kase=1;kase<=T;kase++) 109 { 110 scanf("%d%d",&n,&d); 111 for(int i=1;i<=n;i++) 112 { 113 cin>>s; 114 if(i==1) 115 { 116 m=s.size(); 117 src=0; 118 dst=2*n*m+1; 119 DC.init(2*n*m+2); 120 } 121 for(int j=0;j<m;j++) 122 if(s[j]-'0'>0) 123 { 124 int id=(i-1)*m+j+1; 125 DC.AddEdge(id,id+n*m,s[j]-'0'); //拆点,容量为最多能跳出的蜥蜴数 126 if(i<=d ||(i+d)>n ||(j+1)<=d || (j+1+d)>m) DC.AddEdge(id+n*m,dst,INF); //能跳出网格 127 else 128 { 129 for(int x=1;x<=n;x++) 130 for(int y=1;y<=m;y++) 131 { 132 if(x==i && y==j+1) continue; 133 if(abs(x-i)+abs(y-j-1)<=d) DC.AddEdge(id+n*m,(x-1)*m+y,INF); 134 } 135 } 136 } 137 } 138 int sum=0; 139 for(int i=1;i<=n;i++) 140 { 141 cin>>s; 142 for(int j=0;j<m;j++) 143 { 144 if(s[j]=='L') 145 { 146 sum++; 147 int id=(i-1)*m+j+1; 148 DC.AddEdge(src,id,1); 149 } 150 } 151 } 152 int ans=sum-DC.Maxflow(src,dst); 153 if(ans==0) printf("Case #%d: no lizard was left behind.\n",kase); 154 else if(ans==1) printf("Case #%d: 1 lizard was left behind.\n",kase); 155 else printf("Case #%d: %d lizards were left behind.\n",kase,ans); 156 } 157 return 0; 158 }