HDU2732 Leapin Lizards(拆点+网络流)
您的流浪蜥蜴排进入您正在探索的迷宫中的一个陌生房间。当您到处寻找隐藏的宝藏时,其中一个菜鸟踩在一块看起来纯真的石头上,房间的地板突然消失了!排中的每只蜥蜴都站在看似脆弱的柱子上,下面开始有熊熊大火...不要留下任何蜥蜴!尽可能多地把蜥蜴带出房间,并报告伤亡人数。
房间中的支柱排列成网格,每个支柱与支柱的东,西,北和南相距一个单位。网格边缘的支柱与房间的边缘相距一个单位(安全)。并非所有支柱都一定有蜥蜴。蜥蜴可以跳到其当前d个单位内的任何空置支柱。站在房间边缘跳跃距离内的一根柱子上的蜥蜴可能总是会跳到安全的地方...但是有一个陷阱:每个柱子在每次跳跃后都会变弱,并且很快会塌陷,不再可被其他蜥蜴使用。跳到支柱上不会导致其变弱或塌陷。只是从中跳出来,会使其减弱并最终崩溃。在任何给定时间,只有一只蜥蜴在支柱上。
输入值
输入文件将以包含一个表示测试用例数量的单个整数的行开始,最多为25。每个测试用例将从包含一个表示映射中的行数的单个正整数n的行开始,然后是一个非负整数d,代表蜥蜴的最大跳跃距离。接下来是两张地图,每张地图都是字符地图,每行一行。第一张地图的每个位置都将包含一个数字(0-3),代表该位置的支柱在塌陷之前将持续的跳动次数(0表示那里没有支柱)。接下来是第二张地图,在蜥蜴在支柱上的每个位置都带有一个“ L”,并带有一个“。”。每个空的支柱。没有柱子的位置上永远不会有蜥蜴。每个输入图都保证是一个大小为n x m的矩形,其中1≤n≤20和1≤m≤20。跳跃距离为
总是1≤d≤3。
输出量
对于每种输入情况,请打印一行,其中包含无法逃脱的蜥蜴数量。该格式应遵循以下提供的示例。
真的是很常见的套路了。
#include<bits/stdc++.h> using namespace std; const int maxn=2e5+100; const int inf=1e9; struct node { int u,v,w,nxt; }edge[maxn<<1]; int head[maxn],tot; void addedge (int u,int v,int w) { edge[tot].u=u; edge[tot].v=v; edge[tot].w=w; edge[tot].nxt=head[u]; head[u]=tot++; edge[tot].u=v; edge[tot].v=u; edge[tot].w=0; edge[tot].nxt=head[v]; head[v]=tot++; } int dep[maxn],inq[maxn],cur[maxn],wjm,maxflow,s,t; bool bfs () { for (int i=0;i<=t;i++) { cur[i]=head[i]; dep[i]=inf; inq[i]=0; } dep[s]=0; queue<int> q; q.push(s); while (q.size()) { int u=q.front(); q.pop(); inq[u]=0; for (int i=head[u];i!=-1;i=edge[i].nxt) { int v=edge[i].v; if (dep[v]>dep[u]+1&&edge[i].w) { dep[v]=dep[u]+1; if (inq[v]==0) { q.push(v); inq[v]=1; } } } } if (dep[t]!=inf) return 1; return 0; } int dfs (int u,int flow) { int increase=0; if (u==t) { wjm=1; maxflow+=flow; return flow; } int used=0; for (int i=cur[u];i!=-1;i=edge[i].nxt) { cur[u]=i; int v=edge[i].v; if (edge[i].w&&dep[v]==dep[u]+1) { if (increase=dfs(v,min(flow-used,edge[i].w))) { used+=increase; edge[i].w-=increase; edge[i^1].w+=increase; if (used==flow) break; } } } return used; } int Dinic () { while (bfs()) { wjm=1; while (wjm==1) { wjm=0; dfs(s,inf); } } return maxflow; } string ss[maxn]; int a[1010][1010];//表示石柱矩阵 double getDis (int A,int B,int C,int D) { return sqrt((A-C)*(A-C)+(B-D)*(B-D)); } int n,m,d; int main () { int _; scanf("%d",&_); for (int ca=1;ca<=_;ca++) { scanf("%d%d",&n,&d); // 0为源点 // 1~n*m为上点 // n*m+1~n*m*2为下点 // n*m*2+1为汇点 // 源点向每个蜥蜴点的上点连容量为1的边,表示只有一只蜥蜴 // 每个点的上点向下点连一条容量为石柱高度的边 // 每个点的下点向周围距离d以内的上点连一条容量为inf的边 // 每个在边缘的点的下点向汇点连一条容量为inf的边 for (int i=0;i<n;i++) cin>>ss[i]; m=ss[0].size(); s=0;t=n*m*2+1; for (int i=0;i<=t;i++) head[i]=-1;tot=0;maxflow=0;wjm=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) a[i][j]=ss[i-1][j-1]-'0'; for (int i=0;i<n;i++) cin>>ss[i]; int sum=0; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { if (ss[i-1][j-1]=='L') addedge(s,(i-1)*m+j,1),sum++; addedge((i-1)*m+j,(i-1)*m+j+n*m,a[i][j]); for (int k=1;k<=n;k++) { for (int q=1;q<=m;q++) { if (getDis(i,j,k,q)<=d) addedge((i-1)*m+j+n*m,(k-1)*m+q,inf); } } if (i<=d||n-i<d||j<=d||m-j<d) addedge((i-1)*m+j+n*m,t,inf); } } printf("Case #%d: ",ca); int ans=sum-Dinic(); if (ans==0) printf("no lizard was left behind.\n"); else if (ans==1) printf("1 lizard was left behind.\n"); else printf("%d lizards were left behind.\n",ans); } }