【HNOI2007】紧急疏散
题面
题解
\(\text{HNOI2007}\)真的恐怖
所以这道题非常码
二分答案,将门拆点,于是就变成了一个二分图匹配的题目
反正很恶心
代码
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<queue>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define clear(x, y) memset(x, y, sizeof(x))
inline int read()
{
int data = 0, w = 1; char ch = getchar();
while(ch != '-' && (!isdigit(ch))) ch = getchar();
if(ch == '-') w = -1, ch = getchar();
while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
return data * w;
}
const int N(25), INF(0x3f3f3f3f);
const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};
int n, m; char g[N][N];
namespace DINIC
{
const int maxn(5e4 + 10), maxm(1e6 + 10);
struct edge { int next, to, cap; } e[maxm];
int head[maxn], e_num = -1, S, T, q[maxn], tail, lev[maxn], cur[maxn];
inline void add_edge(int from, int to, int cap)
{
e[++e_num] = (edge) {head[from], to, cap}; head[from] = e_num;
e[++e_num] = (edge) {head[to], from, 0 }; head[to] = e_num;
}
int bfs()
{
clear(lev, 0); q[tail = lev[S] = 1] = S;
for(RG int i = 1; i <= tail; i++)
{
int x = q[i];
for(RG int j = head[x]; ~j; j = e[j].next)
{
int to = e[j].to;
if(lev[to] || (!e[j].cap)) continue;
lev[q[++tail] = to] = lev[x] + 1;
}
}
return lev[T];
}
int dfs(int x, int f)
{
if(x == T || (!f)) return f;
int ans = 0, cap;
for(RG int &i = cur[x]; ~i; i = e[i].next)
{
int to = e[i].to;
if(e[i].cap && lev[to] == lev[x] + 1)
{
cap = dfs(to, std::min(f - ans, e[i].cap));
e[i].cap -= cap, e[i ^ 1].cap += cap, ans += cap;
if(ans == f) break;
}
}
return ans;
}
inline int main()
{
int ans = 0;
while(bfs())
{
for(RG int i = S; i <= T; i++) cur[i] = head[i];
ans += dfs(S, INF);
}
return ans;
}
}
std::vector<int> dX, dY, pX, pY;
int dis[N][N][N][N];
void BFS(int x, int y, int d[N][N])
{
std::queue<int> qx, qy;
d[x][y] = 0; qx.push(x), qy.push(y);
while(!qx.empty())
{
x = qx.front(); qx.pop();
y = qy.front(); qy.pop();
for(RG int k = 0; k < 4; k++)
{
int tx = x + dx[k], ty = y + dy[k];
if(tx < 1 || tx > n || ty < 1 || ty > m) continue;
if(g[tx][ty] != '.' || d[tx][ty] != -1) continue;
d[tx][ty] = d[x][y] + 1;
qx.push(tx), qy.push(ty);
}
}
}
bool check(int t)
{
int d = dX.size(), p = pX.size(); DINIC::e_num = -1;
clear(DINIC::head, -1); static int idcnt, id_door[N * N][N], id_p[N];
DINIC::S = idcnt = 1;
for(RG int i = 1; i <= t; i++)
for(RG int j = 1; j <= d; j++)
id_door[i][j] = ++idcnt;
for(RG int i = 1; i <= t; i++)
for(RG int j = 1; j <= d; j++)
DINIC::add_edge(DINIC::S, id_door[i][j], 1);
for(RG int i = 1; i <= p; i++)
id_p[i] = ++idcnt;
DINIC::T = ++idcnt;
for(RG int i = 1; i <= p; i++)
DINIC::add_edge(id_p[i], DINIC::T, 1);
for(RG int i = 0; i < d; i++)
for(RG int j = 0; j < p; j++)
{
int ds = dis[dX[i]][dY[i]][pX[j]][pY[j]];
if(ds < 0) continue;
for(RG int k = ds; k <= t; k++)
DINIC::add_edge(id_door[k][i + 1], id_p[j + 1], 1);
}
return DINIC::main() == p;
}
void Solve()
{
int lim = n * m; clear(dis, -1);
for(RG int x = 1; x <= n; x++)
for(RG int y = 1; y <= m; y++)
if(g[x][y] == 'D') dX.push_back(x),
dY.push_back(y), BFS(x, y, dis[x][y]);
else if(g[x][y] == '.') pX.push_back(x), pY.push_back(y);
int L = -1, R = lim + 1, ans = R;
while(L <= R)
{
int mid = (L + R) >> 1;
if(check(mid)) R = mid - 1, ans = mid;
else L = mid + 1;
}
if(ans > lim) puts("impossible");
else printf("%d\n", ans);
}
int main()
{
n = read(), m = read();
for(RG int i = 1; i <= n; i++)
scanf("%s", g[i] + 1);
Solve();
return 0;
}
【HNOI2007】紧急疏散的更多相关文章
- Bzoj1189 [HNOI2007]紧急疏散evacuate
1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2293 Solved: 715 Descr ...
- BZOJ1189: [HNOI2007]紧急疏散evacuate 二分+最大流
1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1132 Solved: 412[Submi ...
- BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )
我们可以BFS出每个出口到每个人的最短距离, 然后二分答案, 假设当前答案为m, 把一个出口拆成m个表示m个时间, 点u到出口v的距离为d, 那么u->v的[d, m]所有点连边, 然后跑匈牙利 ...
- [HNOI2007]紧急疏散EVACUATE (湖南2007年省选)
[HNOI2007]紧急疏散EVACUATE 题目描述 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面 ...
- bzoj千题计划132:bzoj1189: [HNOI2007]紧急疏散evacuate
http://www.lydsy.com/JudgeOnline/problem.php?id=1189 二分答案 源点向人连边,流量为1 门拆为mid个点,同一个门的第j个点向第j+1个点连边,流量 ...
- bzoj 1189 [HNOI2007]紧急疏散evacuate 二分+网络流
[HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3626 Solved: 1059[Submit][St ...
- 【二分答案】【最大流】[HNOI2007]紧急疏散EVACUATE
[HNOI2007]紧急疏散EVACUATE 题目描述 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面 ...
- 【BZOJ1189】[HNOI2007]紧急疏散evacuate 动态加边网络流
[BZOJ1189][HNOI2007]紧急疏散evacuate Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空 ...
- AC日记——[HNOI2007]紧急疏散evacuate bzoj 1189
[HNOI2007]紧急疏散evacuate 思路: 处理每个人到门的最短路: 然后二分答案: s向人连边流量1: 人向门拆分后的点连边流量1(拆成400,前一个点连当前点流量INF): 然后门向t连 ...
- P3191 [HNOI2007]紧急疏散EVACUATE(费用流)
P3191 [HNOI2007]紧急疏散EVACUATE 费用流+卡常优化 我们只关心一个人通过门时的时间,在空地的行走时间可以分层维护 于是根据时间分层,到门的时候再计算代价,即代价$=$层数 每经 ...
随机推荐
- Eclipse4.6安装Tomcat插件时报错:Unable to read repository at http://tomcatplugin.sf.net/update/content.xml. Received fatal alert: handshake_failure
错误如下: Unable to read repository at http://tomcatplugin.sf.net/update/content.xml.Received fatal aler ...
- asp.net MVC 使用PagedList.MVC实现分页
在上一篇的EF之DB First中,存在以下的两个问题: 1. 添加/编辑页面显示的是属性名称,而非自定义的名称(如:姓名.专业...) 2. 添加/编辑时没有加入验证 另外数据展示使用分页 @Htm ...
- 转:eclipse的快捷键
22 21 Eclipse中10个最有用的快捷键组合 一个Eclipse骨灰级开发者总结了他认为最有用但又不太为人所知的快捷键组合.通过这些组合可以更加容易的浏览源代码,使得整体的开发效率和质量得到 ...
- PHPredis安装
一.PHPredis下载链接:https://pan.baidu.com/s/1bz0EaJgDpp2ADQJCJOHJGA 二.解压并进入目录 三.发现没有configure文件,需要安装autoc ...
- 基于easyui开发Web版Activiti流程定制器详解(六)——Draw2d详解(二)
回顾: 上一篇我们介绍了Draw2d整体结构,展示了组件类关系图,其中比较重要的类有Node.Canvas.Command.Port.Connection等,这篇将进一步介绍Draw2d如何使用以及如 ...
- Python3中内置类型bytes和str用法及byte和string之间各种编码转换
Python 3最重要的新特性大概要算是对文本和二进制数据作了更为清晰的区分.文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示.Python 3不会以任意隐式的方式混用str ...
- 【洛谷】【搜索(dfs)】P1363 幻想迷宫
[题目描述:] 幻象迷宫可以认为是无限大的,不过它由若干个N*M的矩阵重复组成.矩阵中有的地方是道路,用'.'表示:有的地方是墙,用'#'表示.LHX和WD所在的位置用'S'表示.也就是对于迷宫中的一 ...
- oracle 禁用/启动job
注意:dbms_job只能在job的所在用户使用,如果broken其它用户的job用dbms_ijob dbms_job只能在当期用户内创建job.修改和删除job,不能对其他用户的job进行操作;s ...
- Fluent Terminal
特性: PowerShell,CMD,WSL或自定义shell的终端 支持选项卡和多个窗口 主题和外观配置 导入/导出主题 导入iTerm主题 全屏模式 可编辑的键绑定 搜索功能 配置shell配置文 ...
- npm发布插件步骤
开发好一个插件后,要想让其他人也能使用该插件需要将插件发布到npm上,具体步骤如下: 1.添加npm用户: npm adduser Username: your name Password: your ...