http://acm.hdu.edu.cn/showproblem.php?pid=2732
题意:
在一个nxm的房间,有一些柱子,每个柱子都有个承受极限,有的柱子上又蜥蜴,问有多少蜥蜴跳不出去
思路:
一个超级源点S与蜥蜴相连,能跳出去的柱子与一个超级汇点相连,柱子之间相连,一个最大流模版题
#include <iostream>
#include <string.h>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <stdio.h>
#include <deque>
using namespace std;
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define maxn 10005
#define eps 0.00000001
#define PI acos(-1.0)
struct Edge{
int V, Weight, Next;
}edges[maxn << 2];
char Height[maxn][maxn];
char Maze[maxn][maxn];
int head[maxn << 1], Depth[maxn << 1], gap[maxn << 1], Cur[maxn << 1];
int tot, maxFlow, aug, isFind;
int S = 0, TT;
int N, D, MM, Cnt, Ans;
void init() {
tot = 0;
maxFlow = 0;
memset(head, -1, sizeof(head));
S = 0;
}
void AddEdge(int u, int v, int w) {
edges[tot].V = v;
edges[tot].Weight = w;
edges[tot].Next = head[u];
head[u] = tot ++;
edges[tot].V = u;
edges[tot].Weight = 0;
edges[tot].Next = head[v];
head[v] = tot ++;
}
bool Bfs(int Start, int End) {
memset(Depth, -1, sizeof(Depth));
std::queue<int> Que;
Depth[Start] = 0;
Que.push(Start);
while (!Que.empty()) {
int Vertex = Que.front();
Que.pop();
for (int i = head[Vertex]; i != -1; i = edges[i].Next) {
if (Depth[edges[i].V] == -1 && edges[i].Weight > 0) {
Depth[edges[i].V] = Depth[Vertex] + 1;
Que.push(edges[i].V);
}
}
}
return Depth[End] != -1;
}
int Dfs(int Vertex, int End, int NowFlow) {
if (Vertex == End || NowFlow == 0) {
return NowFlow;
}
int UsableFlow = 0, FindFlow;
for (int &i = Cur[Vertex]; i != -1; i = edges[i].Next) {
if (edges[i].Weight > 0 && Depth[edges[i].V] == Depth[Vertex] + 1) {
FindFlow = Dfs(edges[i].V, End, std::min(NowFlow - UsableFlow, edges[i].Weight));
if (FindFlow > 0) {
edges[i].Weight -= FindFlow;
edges[i ^ 1].Weight += FindFlow;
UsableFlow += FindFlow;
if (UsableFlow == NowFlow) {
return NowFlow;
}
}
}
}
if (!UsableFlow) {
Depth[Vertex] = -2;
}
return UsableFlow;
}
int Dinic(int Start, int End) {
int MaxFlow = 0;
while (Bfs(Start, End)) {
for (int i = 0; i <= N * MM * 2 + 1; ++i) {
Cur[i] = head[i];
}
MaxFlow += Dfs(Start, End, INF);
}
return MaxFlow;
}
int main(int argc, const char * argv[]) {
int T;
scanf("%d", &T);
for (int Case = 1; Case <= T; ++Case) {
init();
scanf("%d%d", &N, &D);
for (int i = 1; i <= N; ++i) {
scanf("%s", Height[i]);
getchar();
}
MM = strlen(Height[1]);
for (int i = 1; i <= N; ++i) {
scanf("%s", Maze[i]);
getchar();
}
Cnt = 0;
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= MM; ++j) {
int Num = MM * (i - 1) + j;
AddEdge(Num, N * MM + Num, (Height[i][j - 1] - '0'));
if (Maze[i][j - 1] == 'L') {
AddEdge(0, Num, 1);
Cnt++;
}
bool flag = 0;
for (int k = i - D; k <= i + D; ++k) {
for (int l = j - D; l <= j + D; ++l) {
if (k == i && l == j) {
continue;
}
if (k > 0 && k <= N && l > 0 && l <= MM) {
if (abs(k - i) + abs(l - j) <= D) {
AddEdge(N * MM + Num, MM * (k - 1) + l, INF);
}
}
else if (abs(k - i) + abs(l - j) <= D) {
if (!flag) {
AddEdge(N * MM + Num, N * MM * 2 + 1, INF);
flag = 1;
}
}
}
}
}
}
Ans = Cnt - Dinic(0, N * MM * 2 + 1);
if (Ans == 0) {
printf("Case #%d: no lizard was left behind.\n", Case);
}
else if (Ans == 1) {
printf("Case #%d: %d lizard was left behind.\n", Case, Ans);
}
else {
printf("Case #%d: %d lizards were left behind.\n", Case, Ans);
}
}
return 0;
}
SAP
#include <iostream>
#include <string.h>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <stdio.h>
#include <deque>
using namespace std;
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define maxn 10005
#define eps 0.00000001
#define PI acos(-1.0)
struct Edge{
int v, w, nxt;
}edge[maxn << 2];
char Height[maxn][maxn];
char Maze[maxn][maxn];
int head[maxn << 1], gap[maxn << 1], dis[maxn << 1], cur[maxn << 1], aug[maxn << 1], pre[maxn << 1], tot, n, st, en;
int S, TT;
int N, D, MM, Cnt, Ans;
void init() {
tot = 0;
memset(head, -1, sizeof(head));
}
void addEdge(int u, int v, int w) {
edge[tot].v = v;
edge[tot].w = w;
edge[tot].nxt = head[u];
head[u] = tot ++;
edge[tot].v = u;
edge[tot].w = 0;
edge[tot].nxt = head[v];
head[v] = tot ++;
}
int SAP(int n){
int max_flow=0,u=S,v;
int id,mindep;
aug[S]=INF;
pre[S]=-1;//st的父节点为-1
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
gap[0]=n;//初始位置为0的有n个
for(int i=0;i<=n;i++)
cur[i]=head[i]; // 初始化当前弧为第一条弧
while(dis[S]<n){ //当dis[st]< n时
int flag=0;
if(u==TT){
max_flow+=aug[TT];
for(v=pre[TT];v!=-1;v=pre[v]){ // 路径回溯更新残留网络
id=cur[v];
edge[id].w-=aug[TT];
edge[id^1].w+=aug[TT];
aug[v]-=aug[TT]; // 修改可增广量,以后会用到
if(edge[id].w==0) // 不回退到源点,仅回退到容量为0的弧的弧尾
u=v;
}
}
for(int i=cur[u];i!=-1;i=edge[i].nxt){
v=edge[i].v; // 从当前弧开始查找允许弧
if(edge[i].w>0 && dis[u]==dis[v]+1){ // 找到允许弧
flag=1;
pre[v]=u;
cur[u]=i;//记录u这个点的边的编号
aug[v]=min(aug[u],edge[i].w);//更新aug[v]
u=v;//u向下
break;
}
}
if(!flag){//没找到弧
if(--gap[dis[u]]==0) /* gap优化,层次树出现断层则结束算法 */
break;
mindep = n;
cur[u]=head[u];
for(int i=head[u];i!=-1;i=edge[i].nxt){
v=edge[i].v;
if(edge[i].w>0 && dis[v]<mindep){
mindep=dis[v];
cur[u]=i; // 修改标号的同时修改当前弧
}
}
dis[u]=mindep+1;
gap[dis[u]]++;
if(u!=S) // 回溯继续寻找允许弧
u=pre[u];
}
}
return max_flow;
}
int main(int argc, const char * argv[]) {
int T;
scanf("%d", &T);
for (int Case = 1; Case <= T; ++Case) {
init();
scanf("%d%d", &N, &D);
for (int i = 1; i <= N; ++i) {
scanf("%s", Height[i]);
getchar();
}
MM = (int)strlen(Height[1]);
TT = 2 * N * MM + 2;
S = 2 * N * MM + 1;
for (int i = 1; i <= N; ++i) {
scanf("%s", Maze[i]);
getchar();
}
Cnt = 0;
for (int i = 1; i <= N; ++i) {
for (int j = 1; j <= MM; ++j) {
int Num = MM * (i - 1) + j;
addEdge(Num, N * MM + Num, (Height[i][j - 1] - '0'));
if (Maze[i][j - 1] == 'L') {
addEdge(S, Num, 1);
Cnt++;
}
bool flag = 0;
for (int k = i - D; k <= i + D; ++k) {
for (int l = j - D; l <= j + D; ++l) {
if (k == i && l == j) {
continue;
}
if (k > 0 && k <= N && l > 0 && l <= MM) {
if (abs(k - i) + abs(l - j) <= D) {
addEdge(N * MM + Num, MM * (k - 1) + l, INF);
}
}
else if (abs(k - i) + abs(l - j) <= D) {
if (!flag) {
addEdge(N * MM + Num, TT, INF);
flag = 1;
}
}
}
}
}
}
Ans = Cnt - SAP(TT + 1);
if (Ans == 0) {
printf("Case #%d: no lizard was left behind.\n", Case);
}
else if (Ans == 1) {
printf("Case #%d: %d lizard was left behind.\n", Case, Ans);
}
else {
printf("Case #%d: %d lizards were left behind.\n", Case, Ans);
}
}
return 0;
}