书上写的是UVa 12011, 实际上是 12264

参考了https://blog.csdn.net/xl2015190026/article/details/51902823

这道题就是求出一种最优的移动士兵的方式, 使得与敌方相邻的阵营中最少的士兵最多

因为只能在我方的阵营中移动士兵, 所以建模的时候不用加入地方阵营的点。

首先因为士兵只能移动一次, 所以把点拆成两个点, 入点和出点。

设阵营士兵的人数为k[i]

那么源点到入点连一条弧, 容量为k[i], 然后入点和出点再连

一条弧, 容量为k[i]

然后因为士兵可以移动, 所以相邻的阵营之间, 如i与j, 那么i的入点

和j的出点连一条弧, 容量为最多可以给的士兵的数量, 可以设为k[i]

实际上不可能给k[i]那么多个,因为每个阵营少留下一个人。

但是容量多了没事, 反正多了也流不过来。这里设为无穷大效果也是一样的

这类弧表示相邻的阵营之间可以有士兵移动

然后现在要从出点到汇点连一条弧, 这条弧的流量表示最终这个阵营的人数

中间入点和出点的弧有流量, 就是表示士兵是在原来的阵营还是去其他阵营

流到最后每个阵营流出去的流量就是最后这个阵营的人数。

然后容量为多少呢?

首先要使最少的尽量多, 那么如果这个阵营不与敌方阵营相邻, 那么也就是说

这个阵营只要满足人数大于1就可以了。那么显然, 为了给那些与敌方阵营相邻

的阵营更多的人数, 那么这类阵营的人数干脆就为1了。

所以容量为1。如果与地方阵营相邻, 要使最少的最多, 那么在肯定是平均分最好。

那么这个平均的值是不确定的, 所以我们要二分

也就是说二分答案, 二分的这个值就是弧的容量。

最后如果满载的话说明满足条件, 那么就符合。

#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std; const int MAXN = 212;
struct Edge{ int from, to, cap, flow; };
vector<Edge> edges;
vector<int> g[MAXN];
int cur[MAXN], h[MAXN], k[MAXN], f[MAXN];
int n, m, s, t;
char map[MAXN][MAXN]; void AddEdge(int from, int to, int cap)
{
edges.push_back(Edge{from, to, cap, 0});
edges.push_back(Edge{to, from, 0, 0});
g[from].push_back(edges.size() - 2);
g[to].push_back(edges.size() - 1);
} bool bfs()
{
queue<int> q;
q.push(s);
memset(h, 0, sizeof(h));
h[s] = 1; while(!q.empty())
{
int x = q.front(); q.pop();
REP(i, 0, g[x].size())
{
Edge& e = edges[g[x][i]];
if(e.cap > e.flow && !h[e.to])
{
h[e.to] = h[x] + 1;
q.push(e.to);
}
}
} return h[t];
} int dfs(int x, int a)
{
if(x == t || a == 0) return a;
int flow = 0, f;
for(int& i = cur[x]; i < g[x].size(); i++)
{
Edge& e = edges[g[x][i]];
if(h[x] + 1 == h[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0)
{
e.flow += f;
edges[g[x][i] ^ 1].flow -= f;
flow += f;
if((a -= f) == 0) break;
}
}
return flow;
} int maxflow()
{
int flow = 0;
while(bfs())
{
memset(cur, 0, sizeof(cur));
flow += dfs(s, 1e9);
}
return flow;
} int make_edges(int cap)
{
edges.clear();
REP(i, 0, MAXN) g[i].clear();
memset(f, false, sizeof(f)); REP(i, 0, n)
{
if(!k[i]) continue;
AddEdge(s, i, k[i]);
AddEdge(i, i + n, k[i]);
REP(j, 0, n)
if(map[i][j] == 'Y')
{
if(k[j]) AddEdge(i, j + n, k[i]);
else f[i] = true;
}
} int ret = 0;
REP(i, 0, n)
if(k[i])
{
if(f[i]) AddEdge(i + n, t, cap), ret += cap;
else AddEdge(i + n, t, 1), ret++;
}
return ret;
} int main()
{
int T;
scanf("%d", &T); while(T--)
{
scanf("%d", &n);
REP(i, 0, n) scanf("%d", &k[i]);
REP(i, 0, n) scanf("%s", map[i]);
s = 2 * n; t = s + 1; int l = 0, r = MAXN * MAXN;
while(l + 1 < r)
{
int mid = (l + r) >> 1;
if(make_edges(mid) == maxflow()) l = mid;
else r = mid;
}
printf("%d\n", l);
} return 0;
}

紫书 习题 11-10 UVa 12264 (二分答案+最大流)的更多相关文章

  1. 紫书 习题8-14 UVa 1616(二分+小数化分数+精度)

    参考了https://www.cnblogs.com/dwtfukgv/p/5645446.html (1)直接二分答案.说实话我没有想到, 一开始以为是贪心, 以某种策略能得到最优解. 但是想了很久 ...

  2. 紫书 习题 11-9 UVa 12549 (二分图最小点覆盖)

    用到了二分图的一些性质, 最大匹配数=最小点覆盖 貌似在白书上有讲 还不是很懂, 自己看着别人的博客用网络流写了一遍 反正以后学白书应该会系统学二分图的,紫书上没讲深. 目前就这样吧. #includ ...

  3. 紫书 习题 11-8 UVa 1663 (最大流求二分图最大基数匹配)

    很奇怪, 看到网上用的都是匈牙利算法求最大基数匹配 紫书上压根没讲这个算法, 而是用最大流求的. 难道是因为第一个人用匈牙利算法然后其他所有的博客都是看这个博客的吗? 很有可能-- 回归正题. 题目中 ...

  4. 紫书 习题8-12 UVa 1153(贪心)

    本来以为这道题是考不相交区间, 结果还专门复习了一遍前面写的, 然后发现这道题的区间是不是 固定的, 是在一个范围内"滑动的", 只要右端点不超过截止时间就ok. 然后我就先考虑有 ...

  5. 紫书 习题8-7 UVa 11925(构造法, 不需逆向)

    这道题的意思紫书上是错误的-- 难怪一开始我非常奇怪为什么第二个样例输出的是2, 按照紫书上的意思应该是22 然后就不管了,先写, 然后就WA了. 然后看了https://blog.csdn.net/ ...

  6. Risk UVA - 12264 拆点法+最大流+二分 最少流量的节点流量尽量多。

    /** 题目:Risk UVA - 12264 链接:https://vjudge.net/problem/UVA-12264 题意:给n个点的无权无向图(n<=100),每个点有一个非负数ai ...

  7. BZOJ 1738: [Usaco2005 mar]Ombrophobic Bovines 发抖的牛( floyd + 二分答案 + 最大流 )

    一道水题WA了这么多次真是.... 统考终于完 ( 挂 ) 了...可以好好写题了... 先floyd跑出各个点的最短路 , 然后二分答案 m , 再建图. 每个 farm 拆成一个 cow 点和一个 ...

  8. Gym - 101908G 二分答案+最大流

    After the end of the truck drivers' strike, you and the rest of Nlogônia logistics specialists now h ...

  9. BZOJ 1570: [JSOI2008]Blue Mary的旅行( 二分答案 + 最大流 )

    二分答案, 然后对于答案m, 把地点分成m层, 对于边(u, v), 第x层的u -> 第x+1层的v 连边. 然后第x层的u -> 第x+1层的u连边(+oo), S->第一层的1 ...

随机推荐

  1. luogo p3379 【模板】最近公共祖先(LCA)

    [模板]最近公共祖先(LCA) 题意 给一个树,然后多次询问(a,b)的LCA 模板(主要参考一些大佬的模板) #include<bits/stdc++.h> //自己的2点:树的邻接链表 ...

  2. pythone 学习笔记(粗略)

    文档目录 概述 安装 基本语法 数据结构 4.1 数字和字符串类型 4.2 元祖 4.3 列表 4.4 字典 流程语句 5.1 分支结构 5.2 逻辑运算符(if) 5.3 循环 5.3.1 for ...

  3. BZOJ 2141 排队 (三维偏序CDQ+树状数组)

    题目大意:略 洛谷传送门 和 [CQOI2015]动态逆序对 这道题一样的思路 一开始的序列视为$n$次插入操作 把每次交换操作看成四次操作,删除$x$,删除$y$,加入$x$,加入$y$ 把每次操作 ...

  4. [USACO18JAN] Lifeguards S (线段树:扫描线面积)

    扫描线裸题没什么好说的 注意空间不要开小了!!! #include <cstdio> #include <cstring> #include <algorithm> ...

  5. Mysql干货收集

    mysql优化:https://www.cnblogs.com/duanxz/tag/mysql/default.html?page=1

  6. LaTeX 插图片

    本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50240371 这里列出3种LaTeX中 ...

  7. ASP.NET-Session cooike

    Application .Cookie和 Session 两种会话有什么不同 答:Application是用来存取整个网站全局的信息,而Session是用来存取与具体某个访问者关联的信息, Sessi ...

  8. Wing IDE 怎样设置 python版本号

    机器上同一时候装了Python3和Python2,使用Wing IDE, 由于Python2和3是有非常大的差别的,所以时不时的须要更改IDE使用的Python版本号.以下介绍方法: 1.打开Edit ...

  9. [iOS]字符串转字典

    有点时候,我们json中有post请求的网址,这个时候我们须要把网址字符串转换成body体 字典   放在post请求中 NSString *body = [self.url_C_ component ...

  10. Android 6.0 开发人员对系统权限的使用与练习(Permissions Best Practices)

    Permissions Best Practices 在安装的过程中,用户非常easy忽略权限请求. 假设一个用户相应用感觉沮丧或者操心泄漏个人信息,那么这些用户就会不用他或者卸载它. 怎样规避这个问 ...