当前位置:首页 > Windows程序 > 正文

2732 (Leapin Lizards) 网络流

2021-03-27 Windows程序

网络流真的博大精深

题意:
在一个迷宫中,新进了一批小蜥蜴. 然而因为一些原因,出口被封住了,而且迷宫燃起了大火,现在小蜥蜴们急着离开,想要求助于ACMer们,哈哈……
把蜥蜴所在的坐标当做一根有高度为k的柱子,现在每有一只蜥蜴跳出格子,格子的柱子高度就会减少一,直到为0,表示这个格子不能在通过蜥蜴. 题目规定,小蜥蜴们可以从当前格子往周围跳出小于等于d距离的长度.当蜥蜴跳出迷宫的边界,就算这只蜥蜴存活下来了,而那些不能逃出去的,就只能等着被烤成烤肉了.现在想要让更多的蜥蜴逃出,求最后剩下的蜥蜴数;

题解:
这道题目有很深的网络流味道…….,具体建模还是基本的网络流模式,就是虚拟出源点和汇点,再把一些相关联的点通过边和流量联系起来. 具体看下我写的代码吧! 里面有解释具体怎么建边.

/* *********************************************** Author :xdlove Created Time :2015年08月18日 星期二 13时18分54秒 File Name :xd.cpp ************************************************ */ #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std; /******************************** please don‘t hack me!! /(ToT)/~~ __------__ /~ ~ | //^\\//^\| /~~\ || T| |T|:~ | |6 ||___|_|_||:| \__. / o \/‘ | ( O ) /~~~~\ `\ \ / | |~~\ | ) ~------~` /‘ | | | / ____ /~~~)(_/‘ | | | /‘ | ( | | | | \ / __)/ \ \ \ \/ /‘ \ ` \ \|\ / | |\___| \ | \____/ | | /^~> \ _/ < | | \ | | \ \ -^-\ \ | ) `\_______/^\______/ ************************************/ const int MAXN = 3e3 + 5;//点数的最大值 const int MAXM = 1e6 + 5;//边数的最大值 const int INF = 0x3f3f3f3f; struct Edge { int to,next,cap,flow; } edge[MAXM]; //注意是MAXM int tol; int head[MAXN]; int gap[MAXN],dep[MAXN],cur[MAXN]; void init() { tol = 0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w,int rw = 0) { //printf("%d %d %d\n",u,v,w); edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++; } int Q[MAXN]; void BFS(int start,int end) { memset(dep,-1,sizeof(dep)); memset(gap,0,sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[end] = 0; Q[rear++] = end; while(front != rear) { int u = Q[front++]; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(dep[v] != -1)continue; Q[rear++] = v; dep[v] = dep[u] + 1; gap[dep[v]]++; } } } int S[MAXN]; int sap(int start,int end,int N) { BFS(start,end); memcpy(cur,head,sizeof(head)); int top = 0; int u = start; int ans = 0; while(dep[start] < N) { if(u == end) { int Min = INF; int inser; for(int i = 0; i < top; i++) if(Min > edge[S[i]].cap - edge[S[i]].flow) { Min = edge[S[i]].cap - edge[S[i]].flow; inser = i; } for(int i = 0; i < top; i++) { edge[S[i]].flow += Min; edge[S[i]^1].flow -= Min; } ans += Min; top = inser; u = edge[S[top]^1].to; continue; } bool flag = false; int v; for(int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = i; break; } } if(flag) { S[top++] = cur[u]; u = v; continue; } int Min = N; for(int i = head[u]; i != -1; i = edge[i].next) if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if(!gap[dep[u]])return ans; dep[u] = Min + 1; gap[dep[u]]++; if(u != start)u = edge[S[--top]^1].to; } return ans; } char s[22][22],t[22][22]; struct Point { int x,y,v; Point(){ } Point(int _x,int _y,int _v) { x = _x; y = _y; v = _v; } bool operator == (const Point &a) const { return x == a.x && y == a.y; } }p[MAXN]; int mul(int x) { return x * x; } int dist(Point a,Point b) { return mul(a.x - b.x) + mul(a.y - b.y); } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int T,kcase = 0; int n,m,d; cin>>T; while(T--) { init(); scanf("%d %d",&n,&d); d *= d; for(int i = 0; i < n; i++) scanf("%s",s[i]); for(int i = 0; i < n; i++) scanf("%s",t[i]); int ss,tt,tot = 0; int num = 0; m = strlen(s[0]); tt = 2 * n * m + 2; ss = tt - 1; for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { if(t[i][j] == ‘L‘) { num++; addedge(ss,i * m + j,1); //对于每只蜥蜴来说,从源点往其建一流量为1的边,表示他能否逃出去; } if(s[i][j] != ‘0‘) { p[tot++] = Point(i,j,i * m + j); addedge(i * m + j,n * m + i * m + j,s[i][j] - ‘0‘);//对于每一个有柱子的格子来说,自己与自己连一条容量为其键值key的边, //表示其最多只能通过key只蜥蜴; } } } //每个格子相互的连边 for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { Point nn = Point(i,j,0); for(int k = 0; k < tot; k++) { int pd = dist(nn,p[k]); if(i == 0 || j == 0 || i == n - 1 || j == m - 1) { if(pd < d) //对于边界点来说,如果距离之和小于d,则当前蜥蜴可以从这个格子逃出; addedge(n * m + p[k].v,tt,INF);//所以往汇点建一条流量为无穷大的边,表示可以从这个格子逃出的蜥蜴数量不确定,取大一点的值; } if(s[i][j] == ‘0‘ || (nn == p[k])) continue;//key=0或者自己,不建边 if(pd <= d) addedge(n * m + p[k].v,i * m + j,INF);//相邻两个格子之间可以通过无穷只蜥蜴,在没有key值限制的情况下; } } } int ans = sap(ss,tt,2 * n * m + 2); ans = num - ans; printf("Case #%d: ",++kcase); if(ans) printf("%d ",ans); else printf("no "); if(ans > 1) printf("lizards were "); else printf("lizard was "); puts("left behind."); } return 0; }

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/68242.html