【洛谷 P3191】 [HNOI2007]紧急疏散EVACUATE(二分答案,最大流)
题目链接
sb错误调了3hour+。。
bfs预处理出每个\(.\)到每个\(D\)的最短距离。
二分时间\(t\),把每个\(D\)拆成\(t\)个点,这\(t\)个点两两连边,流量\(INF\)表示\(t\)个时刻都可以从这个\(D\)出。
然后枚举所有\(.\),再枚举所有\(D\),如果距离\(dis\)小于\(t\),就从这个\(.\)向这个\(D\)的第\(dis\)个点连一条流量为\(1\)的边,表示从这个时刻开始这个\(.\)可以从这个\(D\)出。
然后求最大流,如果等于\(.\)的个数,说明此\(t\)可行,二分一下即可。
#include <cstdio>
#include <queue>
#include <cstdlib>
#include <cstring>
#define INF 2147483647
using namespace std;
const int MAXN = 300010;
const int N = 440;
const int MAXM = 200010;
char a[N][N];
int b[N][N], c[N][N];
struct point{
    int x, y, time;
}Now;
queue <int> q;
queue <point> Q;
struct Edge{
    int from, to, next, rest;
}e[MAXM];
int head[MAXN], num = 1, s, t, now, n, m, dis[MAXN];
inline void Add(int from, int to, int flow){
    e[++num] = (Edge){ from, to, head[from], flow }; head[from] = num;
    e[++num] = (Edge){ to, from, head[to], 0 }; head[to] = num;
}
inline int id(int i, int j){
    return (i - 1) * m + j;
}
int re(){
    memset(dis, 0, sizeof dis);
    q.push(s); dis[s] = 1;
    while(q.size()){
    	now = q.front(); q.pop();
    	for(int i = head[now]; i; i = e[i].next)
    	   if(e[i].rest && !dis[e[i].to])
    	     dis[e[i].to] = dis[now] + 1, q.push(e[i].to);
    }
    return dis[t];
}
int find(int u, int flow){
    if(u == t || !flow) return flow;
    /*if(u == 448){
    	int xsxs = 1;
    }*/
    int sum = 0, T;
    for(int i = head[u]; i; i = e[i].next)
       if(e[i].rest && dis[e[i].to] == dis[u] + 1){
       	 T = find(e[i].to, min(flow - sum, e[i].rest));
         e[i].rest -= T; e[i ^ 1].rest += T; sum += T;
       }
    if(!sum) dis[u] = 0;
    return sum;
}
int dinic(){
    int ans = 0;
    while(re()) ans += find(s, INF);
    /*for(int i = 1; i <= num; ++i)
       if(e[i].to <= n * m && e[i].from == s)
         if(e[i].rest)
           printf("%d %d %d\n", (e[i].to - 1) / 12 + 1, e[i].to % 12 == 0 ? 12 : e[i].to % 12, e[i].to);
    system("pause");*/
    return ans;
}
int cnt, tot, l[] = {233, -1, 1, 0, 0}, r[] = {666, 0, 0, -1, 1}, vis[N][N], L, R;
void bfs(int x, int y){
    Q.push((point){x, y, 0});
    for(int i = 1; i <= n; ++i)
       for(int j = 1; j <= m; ++j)
          vis[i][j] = 0;
    vis[x][y] = 1;
    while(Q.size()){
        Now = Q.front(); Q.pop();
        for(int i = 1; i <= 4; ++i){
           int X = Now.x + l[i], Y = Now.y + r[i];
           if(!X || !Y || X > n || Y > m || a[X][Y] == 'X' || vis[X][Y]) continue;
           Q.push((point){X, Y, Now.time + 1});
           vis[X][Y] = 1;
           if(b[X][Y]) c[id(x, y)][b[X][Y]] = Now.time + 1;
        }
    }
}
int ans, mid;
int main(){
    scanf("%d%d", &n, &m); s = 290000; t = 300001;
    for(int i = 1; i <= n; ++i)
       scanf("%s", a[i] + 1);
    for(int i = 1; i <= n; ++i)
       for(int j = 1; j <= m; ++j)
           if(a[i][j] == 'D')
             b[i][j] = ++cnt;
           else if(a[i][j] == '.')
             ++tot;
    for(int i = 1; i <= n; ++i)
       for(int j = 1; j <= m; ++j)
          if(a[i][j] == '.')
            bfs(i, j);
    L = 1; R = 400; ans = -1;
    if(tot)
    while(L <= R){
        mid = (L + R) >> 1;
        memset(head, 0, sizeof head);
        num = 1;
        for(int i = 1; i <= n; ++i)
           for(int j = 1; j <= m; ++j)
              if(a[i][j] == '.'){
              	Add(s, id(i, j), 1);
                for(int k = 1; k <= cnt; ++k){
                   int d = id(i, j);
                   if(c[d][k] && c[d][k] <= mid)
                     Add(d, 400 + cnt * c[d][k] + k, 1);
                }
              }
        for(int i = 1; i <= cnt; ++i)
           for(int j = 1; j <= mid; ++j)
              Add(400 + cnt * j + i, t, 1), Add(400 + cnt * j + i, 400 + cnt * j + cnt + i, INF);
        if(dinic() == tot) ans = mid, R = mid - 1;
        else L = mid + 1;
    }
    if(ans == -1) printf("impossible\n");
    else printf("%d\n", ans);
    return 0;
}
												
											【洛谷 P3191】 [HNOI2007]紧急疏散EVACUATE(二分答案,最大流)的更多相关文章
- 洛谷 P3191 [HNOI2007]紧急疏散EVACUATE(网络最大流)
		
题解 二分答案+Dinic最大流 二分答案\(mid\) 把门拆成\(mid\)个时间点的门 相邻时间的门连一条\(inf\)的边 预处理出每个门到每个人的最短时间 为\(dis[k][i][j]\) ...
 - BZOJ1189: [HNOI2007]紧急疏散evacuate(二分答案,最大流)
		
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一 块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是 ...
 - P3191 [HNOI2007]紧急疏散EVACUATE(费用流)
		
P3191 [HNOI2007]紧急疏散EVACUATE 费用流+卡常优化 我们只关心一个人通过门时的时间,在空地的行走时间可以分层维护 于是根据时间分层,到门的时候再计算代价,即代价$=$层数 每经 ...
 - BZOJ1189: [HNOI2007]紧急疏散evacuate 二分+最大流
		
1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1132 Solved: 412[Submi ...
 - bzoj 1189 [HNOI2007]紧急疏散evacuate 二分+网络流
		
[HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3626 Solved: 1059[Submit][St ...
 - [CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)
		
[CodePlus 2017 11月赛&洛谷P4058]木材 Description 有 n棵树,初始时每棵树的高度为 Hi ,第 i棵树每月都会长高 Ai.现在有个木料长度总量为 S的订单, ...
 - 洛谷P4589 [TJOI2018]智力竞赛(二分答案 二分图匹配)
		
题意 题目链接 给出一个带权有向图,选出n + 1n+1条链,问能否全部点覆盖,如果不能,问不能覆盖的点权最小值最大是多少 Sol TJOI怎么净出板子题 二分答案之后直接二分图匹配check一下. ...
 - 洛谷 P1824  进击的奶牛 【二分答案】(求最大的最小值)
		
题目链接:https://www.luogu.org/problemnew/show/P1824 题目描述 Farmer John建造了一个有N(2<=N<=100,000)个隔间的牛棚, ...
 - 洛谷P3964 [TJOI2013]松鼠聚会 [二分答案,前缀和,切比雪夫距离]
		
题目传送门 松鼠聚会 题目描述 草原上住着一群小松鼠,每个小松鼠都有一个家.时间长了,大家觉得应该聚一聚.但是草原非常大,松鼠们都很头疼应该在谁家聚会才最合理. 每个小松鼠的家可以用一个点x,y表示, ...
 - 洛谷P3576 [POI2014]MRO-Ant colony [二分答案,树形DP]
		
题目传送门 MRO-Ant colony 题目描述 The ants are scavenging an abandoned ant hill in search of food. The ant h ...
 
随机推荐
- 服务器BMC(带外)
			
服务器除了装linux,windows系统外,相应还有一个可通过网线(服务器默认带外地址--可改)连接具体厂商服务器的BMC(Baseboard Management Controller,基板管理控 ...
 - 【Mark】Android应用开发SharedPreferences存储数据的使用方法
			
Android应用开发SharedPreferences存储数据的使用方法 SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的 ...
 - hdu 6435 CSGO(最大曼哈顿距离)
			
题目链接 Problem Description You are playing CSGO. There are n Main Weapons and m Secondary Weapons in C ...
 - bzoj1923[Sdoi2010]外星千足虫(高斯消元)
			
Description Input 第一行是两个正整数 N, M. 接下来 M行,按顺序给出 Charles 这M次使用“点足机”的统计结果.每行 包含一个“01”串和一个数字,用一个空格隔开.“01 ...
 - 【bzoj3064】Tyvj 1518 CPU监控  线段树维护历史最值
			
题目描述 给你一个序列,支持4种操作:1.查询区间最大值:2.查询区间历史最大值:3.区间加:4.区间赋值. 输入 第一行一个正整数T,表示Bob需要监视CPU的总时间. 然后第二行给出T个数表示在你 ...
 - spring的事务传播特性
			
PROPAGATION_REQUIRED(常用) Support a current transaction; create a new one if none exists. 支持一个当前事务;如 ...
 - 【比赛】HNOI2018 游戏
			
考试的时候线段树区间查询的return条件打成了l==r....于是光荣爆20(线段树都不会打了?) 看膜博士的题解 #include<bits/stdc++.h> #define ui ...
 - BZOJ3261:最大异或和——题解
			
http://www.lydsy.com/JudgeOnline/problem.php?id=3261 给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类型: 1.A x:添加 ...
 - 洛谷 P1278 单词游戏  【状压dp】
			
题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍,游戏中只 ...
 - IT(然而其实是。。hdu5244?)
			
Time Limit: 3000 ms Memory Limit: 256 MB Description IT = Inverse Transform 两个长度为 \(2^n\) 的序列 \(a,b\ ...