UVA Live 6474 Drop Zone 最小割=最大流
2017-07-16 21:47
302 查看
Time Limit: 3000ms
Problem description
Evacuation missions and supply gathering missions are conducted on a regular basis by special teams.One of the first objectives of these missions is to set up a perimeter with barricades. Barricades arecostly and take time to
set up, so it is important to reduce the number of barricades necessary to blockoff an area.You will be provided with several maps of high-interest drop zones. It is your job to write a programthat will output the minimum number of barricades required for
each drop zone.Zombies will begin their approach from outside the map, thus any open area on the border isaccessible to zombies. Barricades can be placed between any two adjacent open areas (including thedrop zone) to block zombie movement. All zones outside
of the map should be considered open areas.Here is an example of one of the maps you will be provided:
XXX..XXX
XXX..XXX
.....XXX
XXX..XXX
XDDDD.XX
XDDDD...
XXXXXXXX
Symbol Description
X
Impassible, zombies cannot move through these areas
.(period)
Open area, zombies can move through these zones, but not diagonally. Barricadesmay be placed between these areas.
D
Drop zone, this zone must be protected at all costs. Barricades must effectively block zombie movement from the edges of the map to this zone. This area is treated like an open area for zombie movement and barricade placement.
There will be exactly one contiguous drop zone in every map. Drop zones may be on the edges of the map.
一个n*m的地图,字符 ‘.’ 表示可以到达,X表示不可到达,D表示可以到达,是安全地带。
现在要在地图里建一些栅栏,把所有D围起来,使D区域不能从外部边界进入。
这题实际上是在建好的图上求最小割,而最小割和最大流相等,可以用dinic算法求出。
地图上可以互相到达的点之间建一条边,流量为1。
建立一个源点,连接边界上所有可以到达的点,流量取决于该格子有几条边在边界上。
建立一个汇点,连接所有地图上为D的格子,流量为4.(因为可以从最多四个方向进入)
如果D在边界上,直接连接源点和汇点即可,流量取决于D有几条边在边界上。
这样建好图之后,直接跑一遍最大流就可以了。
数据好弱啊,只跑了9ms...
#include <cstdio>
#include <iostream>
#include <string.h>
#include <string>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
const int maxn=25005,maxk=112505,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f;
int num;
int head[maxn],dist[maxn],current[maxn],visit[maxn];
char mp[155][155];
struct Edge {
int from,to,flow,pre;
};
Edge edge[maxk];
void addedge(int from,int to,int flow) {
edge[num]=(Edge){from,to,flow,head[from]};
head[from]=num++;
edge[num]=(Edge){to,from,0,head[to]};
head[to]=num++;
}
bool bfs (int n) {
queue<int> q;
q.push(0);
memset(dist,-1,sizeof(dist));
dist[0]=0;
while (!q.empty()) {
int now=q.front();
q.pop();
for (int i=head[now];i!=-1;i=edge[i].pre) {
int to=edge[i].to;
if (dist[to]==-1&&edge[i].flow>0) {
dist[to]=dist[now]+1;
q.push(to);
}
}
}
return dist
!=-1;
}
int dfs(int now,int flow,int n) {
int f;
if (now==n) return flow;
for (int i=current[now];i!=-1;i=edge[i].pre) {
int to=edge[i].to;
current[now]=i;
if (dist[now]+1==dist[to]&&edge[i].flow>0&&
(f=dfs(to,min(flow,edge[i].flow),n))) {
edge[i].flow-=f;
edge[i^1].flow+=f;
return f;
}
}
return 0;
}
int dinic(int n) {
int sum=0,f;
while (bfs(n)) {
memcpy(current,head,sizeof(head));
while (f=dfs(0,inf,n)) sum+=f;
}
return sum;
}
int main() {
int cas,n,m,i,j,k;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
scanf("%d",&cas);
while (cas--) {
num=0;
scanf("%d%d",&n,&m);
int final=n*m+1;
memset(head,-1,sizeof(head));
for (i=1;i<=n;i++)
scanf("%s",mp[i]+1);
for (i=1;i<=n;i++) {
for (j=1;j<=m;j++) {
int now=(i-1)*m+j;
if (mp[i][j]=='.') {
if (i==1||i==n||j==1||j==m)
addedge(0,now,(i==1)+(i==n)+(j==1)+(j==m));
for (k=0;k<4;k++) {
int nowx=i+dir[k][0],nowy=j+dir[k][1];
if (nowx>0&&nowx<=n&&nowy>0&&nowy<=m)
if (mp[nowx][nowy]!='X')
addedge(now,(nowx-1)*m+nowy,1);
}
}
if (mp[i][j]=='D') {
if (i==1||i==n||j==1||j==m)
addedge(0,final,(i==1)+(i==n)+(j==1)+(j==m));
addedge(now,final,4-((i==1)+(i==n)+(j==1)+(j==m)));
for (k=0;k<4;k++) {
int nowx=i+dir[k][0],nowy=j+dir[k][1];
if (nowx>0&&nowx<=n&&nowy>0&&nowy<=m)
if (mp[nowx][nowy]!='X')
addedge(now,(nowx-1)*m+nowy,1);
}
}
}
}
/* for (i=0;i<num;i++) {
cout << edge[i].from << ' ' << edge[i].to << ' ' << edge[i].flow << endl;
}*/
int ans=dinic(final);
printf("%d\n",ans);
}
return 0;
}
Problem description
Evacuation missions and supply gathering missions are conducted on a regular basis by special teams.One of the first objectives of these missions is to set up a perimeter with barricades. Barricades arecostly and take time to
set up, so it is important to reduce the number of barricades necessary to blockoff an area.You will be provided with several maps of high-interest drop zones. It is your job to write a programthat will output the minimum number of barricades required for
each drop zone.Zombies will begin their approach from outside the map, thus any open area on the border isaccessible to zombies. Barricades can be placed between any two adjacent open areas (including thedrop zone) to block zombie movement. All zones outside
of the map should be considered open areas.Here is an example of one of the maps you will be provided:
XXX..XXX
XXX..XXX
.....XXX
XXX..XXX
XDDDD.XX
XDDDD...
XXXXXXXX
Symbol Description
X
Impassible, zombies cannot move through these areas
.(period)
Open area, zombies can move through these zones, but not diagonally. Barricadesmay be placed between these areas.
D
Drop zone, this zone must be protected at all costs. Barricades must effectively block zombie movement from the edges of the map to this zone. This area is treated like an open area for zombie movement and barricade placement.
There will be exactly one contiguous drop zone in every map. Drop zones may be on the edges of the map.
Input |
The first number, N (1 <= N <= 20), will be the number of maps. For each map, there will be two parameters, R and C (1 <= R, C <= 150), denoting the number of rows and columns in the map, followed by the map itself as described above. Each row will be on its own line and all rows will have the same number of characters equal to C. |
Output |
For each map, print a single line containing the minimum number of barricades required to block off the drop zone. |
Sample Input |
2 7 8 XXX..XXX XXX..XXX .....XXX XXX..XXX XDDDD.XX XDDDD... XXXXXXXX 5 5 XX.XX .DDD. XD.DX X.... X.... |
Sample Output |
3 6 |
现在要在地图里建一些栅栏,把所有D围起来,使D区域不能从外部边界进入。
这题实际上是在建好的图上求最小割,而最小割和最大流相等,可以用dinic算法求出。
地图上可以互相到达的点之间建一条边,流量为1。
建立一个源点,连接边界上所有可以到达的点,流量取决于该格子有几条边在边界上。
建立一个汇点,连接所有地图上为D的格子,流量为4.(因为可以从最多四个方向进入)
如果D在边界上,直接连接源点和汇点即可,流量取决于D有几条边在边界上。
这样建好图之后,直接跑一遍最大流就可以了。
数据好弱啊,只跑了9ms...
#include <cstdio>
#include <iostream>
#include <string.h>
#include <string>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
const int maxn=25005,maxk=112505,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f;
int num;
int head[maxn],dist[maxn],current[maxn],visit[maxn];
char mp[155][155];
struct Edge {
int from,to,flow,pre;
};
Edge edge[maxk];
void addedge(int from,int to,int flow) {
edge[num]=(Edge){from,to,flow,head[from]};
head[from]=num++;
edge[num]=(Edge){to,from,0,head[to]};
head[to]=num++;
}
bool bfs (int n) {
queue<int> q;
q.push(0);
memset(dist,-1,sizeof(dist));
dist[0]=0;
while (!q.empty()) {
int now=q.front();
q.pop();
for (int i=head[now];i!=-1;i=edge[i].pre) {
int to=edge[i].to;
if (dist[to]==-1&&edge[i].flow>0) {
dist[to]=dist[now]+1;
q.push(to);
}
}
}
return dist
!=-1;
}
int dfs(int now,int flow,int n) {
int f;
if (now==n) return flow;
for (int i=current[now];i!=-1;i=edge[i].pre) {
int to=edge[i].to;
current[now]=i;
if (dist[now]+1==dist[to]&&edge[i].flow>0&&
(f=dfs(to,min(flow,edge[i].flow),n))) {
edge[i].flow-=f;
edge[i^1].flow+=f;
return f;
}
}
return 0;
}
int dinic(int n) {
int sum=0,f;
while (bfs(n)) {
memcpy(current,head,sizeof(head));
while (f=dfs(0,inf,n)) sum+=f;
}
return sum;
}
int main() {
int cas,n,m,i,j,k;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
scanf("%d",&cas);
while (cas--) {
num=0;
scanf("%d%d",&n,&m);
int final=n*m+1;
memset(head,-1,sizeof(head));
for (i=1;i<=n;i++)
scanf("%s",mp[i]+1);
for (i=1;i<=n;i++) {
for (j=1;j<=m;j++) {
int now=(i-1)*m+j;
if (mp[i][j]=='.') {
if (i==1||i==n||j==1||j==m)
addedge(0,now,(i==1)+(i==n)+(j==1)+(j==m));
for (k=0;k<4;k++) {
int nowx=i+dir[k][0],nowy=j+dir[k][1];
if (nowx>0&&nowx<=n&&nowy>0&&nowy<=m)
if (mp[nowx][nowy]!='X')
addedge(now,(nowx-1)*m+nowy,1);
}
}
if (mp[i][j]=='D') {
if (i==1||i==n||j==1||j==m)
addedge(0,final,(i==1)+(i==n)+(j==1)+(j==m));
addedge(now,final,4-((i==1)+(i==n)+(j==1)+(j==m)));
for (k=0;k<4;k++) {
int nowx=i+dir[k][0],nowy=j+dir[k][1];
if (nowx>0&&nowx<=n&&nowy>0&&nowy<=m)
if (mp[nowx][nowy]!='X')
addedge(now,(nowx-1)*m+nowy,1);
}
}
}
}
/* for (i=0;i<num;i++) {
cout << edge[i].from << ' ' << edge[i].to << ' ' << edge[i].flow << endl;
}*/
int ans=dinic(final);
printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- UVALive 7264 Kejin Game (最大流最小割)
- UVALIVE 3661 Animal Run <最大-最小原理之一 最大流-最小割原理>
- Taxi Cab Scheme UVALive - 3126 最小路径覆盖解法(必须是DAG,有向无环图) = 结点数-最大匹配
- Error Curves(三分)uvalive 5009 求下凸 (最大值的最小值)
- UVa live6492Welcome Party(二分最大匹配之最小点覆盖)
- Uvalive - 3026 Period (kmp求字符串的最小循环节+最大重复次数)
- UVALive 4872 Underground Cables 最小生成树
- UVAlive 7368 Airports(建图+最小路径覆盖)
- uvalive 3268 二分图匹配 或者 最大流
- UVALive - 4294 Shuffle 映射+取反+最大区间覆盖
- UVaLive/LA 6807 Túnel de Rata(最大生成树)
- Uvalive 7037 The Problem Needs 3D Arrays (最大密集子图)
- UVALive 5713 Qin Shi Huang's National Road System秦始皇修路(MST,最小瓶颈路)
- uvaLive 2387 - Gene Assembly 最大区间调度问题
- Uvalive 4865 Data Recovery 最大流
- (beginer)网络流(最小割最大流) UVA 1212 - Duopoly
- UVAlive 7037 - The Problem Needs 3D Arrays(网络流‘最大密度子图)
- [UVALive 7264] Kejin Game(最小割)
- UVA 10099 最大的最小边。。
- 最大流最小割 UVA - 10480