HDU - 2732 Leapin' Lizards (拆点最大流)
题意:有N*M的矩形,每个格点有一个柱子,每根柱子有高度c,允许蜥蜴经过这根柱子c次,开始有一些蜥蜴在某些柱子上,它们要跳出这个矩形,每步最大能跳d个单位,求最少有多少蜥蜴不能跳出这个矩形。
分析:转化为求最多有多少蜥蜴能跳出,则变为最大流问题。经典的建图思路,将每个柱子视作点,将其拆为入点和出点,入点到出点建一条容量为c的边,若一个点距离距离边界小于d,建边。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define mp(x,y) make_pair(x,y)
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int maxn = 1e3+5;
bool vis[maxn];
struct Edge{
int from, to,cap,flow;
};
int cost[maxn];
struct Dinic
{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
void init(int n){
this->n = n;
for(int i=0;i<=n;++i){
G[i].clear();
}
edges.clear();
}
void AddEdge(int from,int to,int cap){
edges.push_back((Edge){from,to,cap,0});
edges.push_back((Edge){to,from,0,0});
m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool BFS(){
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(s);
d[s] = 0;
vis[s] = 1;
while(!q.empty()){
int x = q.front(); q.pop();
for(int i=0;i<G[x].size();i++){
Edge &e = edges[G[x][i]];
if(!vis[e.to] && e.flow < e.cap){
vis[e.to] = 1;
d[e.to] = d[x] + 1;//层次图
q.push(e.to);
}
}
}
return vis[t];//能否到汇点,不能就结束
}
int DFS(int x,int a)//x为当前节点,a为当前最小残量
{
if(x == t || a == 0) return a;
int flow = 0 , r;
for(int& i = cur[x];i < G[x].size();i++){
Edge& e = edges[G[x][i]];
if(d[x] + 1 == d[e.to] && (r = DFS(e.to , min(a,e.cap - e.flow) ) ) > 0 ){
e.flow += r;
edges[G[x][i] ^ 1].flow -= r;
flow += r;//累加流量
a -= r;
if(a == 0) break;
}
}
return flow;
}
int MaxFlow(int s,int t){
this->s = s;
this->t = t;
int flow = 0;
while(BFS()){
memset(cur,0,sizeof(cur));
flow += DFS(s,INF);
}
return flow;
}
}F;
char str[maxn];
int G[22][22];
int h,w,d;
bool out(int x,int y)
{
if(x<0||x>=h||y<0||y>=w) return true;
return false;
}
void build(int x,int y)
{
int all = w*h;
int ed = 2*w*h+1;
int u = x*w+y;
F.AddEdge(x*w+y,x*w+y+all,G[x][y]);
if(x-d<0 ||x+d>=h||y-d<0 ||y+d>=w){
F.AddEdge(u+all,ed,INF);
return;
}
for(int i=0;i<h;++i){
for(int j=0;j<w;++j){
if(i==x && j==y) continue;
if(abs(x-i)+abs(y-j)<=d){
F.AddEdge(u+all,i*w+j,INF);
}
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int N,M,T,cas=1; scanf("%d",&T);
while(T--){
int u,v,tmp,base;
int st,ed;
scanf("%d %d",&h,&d);
for(int i=0;i<h;++i){
scanf("%s",str);
if(i==0){
w = strlen(str);
base = w*h;
st = 2*h*w,ed = st+1;
F.init(ed+1);
}
for(int j=0;j<w;++j){
G[i][j] = (int)(str[j]-'0');
}
}
for(int i=0;i<h;++i){
for(int j=0;j<w;++j){
if(!G[i][j]) continue;
build(i,j);
}
}
int tot = 0;
for(int i=0;i<h;++i){
scanf("%s",str);
for(int j=0;j<w;++j){
char c = str[j];
if(c=='L'){
tot++;
u = i*w+j;
F.AddEdge(st,u,1); //源点加边
}
}
}
int res= tot - F.MaxFlow(st,ed);
printf("Case #%d: ",cas++);
if(!res) printf("no lizard was left behind.\n");
else if(res==1) printf("1 lizard was left behind.\n");
else printf("%d lizards were left behind.\n",res);
}
return 0;
}
为了更好的明天