UVa12264 Risk(最大流)
题目
Source
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3416
Description
Risk is a board game played on a world map. This world is divided into regions by borders. Each region is controlled by a player (either you or one of your opponents). Any region that you control contains a positive number of your armies.
In each turn, you are allowed to move your armies. Each of your armies may either stay where it is, or move from a region to a bordering region under your control. The movements are performed one by one, in an order of your choice. At all times, each region must contain at least one army.
For strategic purposes, it is important to move your armies to regions that border your opponents’regions and minimize the number of armies on your regions that are totally surrounded by other regions under your control. You want your weakest link, i.e., the border region with the minimum number of armies, to be as strong as possible. What is the maximum number of armies that can be placed on it after one turn?
Input
On the first line a positive integer: the number of test cases, at most 100. After that per test case:
• One line with an integer n (1 ≤ n ≤ 100): the number of regions.
• One line with n integers ai (0 ≤ ai ≤ 100): the number of your armies on each region. A number 0 indicates that a region is controlled by your opponents, while a positive number indicates that it is under your control.
• n lines with n characters, where each character is either ‘Y’ or ‘N’. The i-th character of the j-th line is ‘Y’ if regions i and j border, and ‘N’ otherwise. This relationship is symmetric and the i-th character of the i-th line will always be ‘N’.
In every test case, you control at least one region, and your opponents control at least one region. Furthermore, at least one of your regions borders at least one of your opponents’regions.
Output
Per test case:
• One line with an integer: the maximum number of armies on your weakest border region after one turn of moving
Sample Input
2
3
1 1 0
NYN
YNY
NYN
7
7 3 3 2 0 0 5
NYNNNNN
YNYYNNN
NYNYYNN
NYYNYNN
NNYYNNN
NNNNNNY
NNNNNYN
Sample Output
1
4
分析
题目大概说有N个点,有些被自己占了有些被敌人占了,然后这N个点有几个是相邻的。一开始己方点有几个士兵,一个回合中可以选择某几个己方点的士兵移动到相邻的己方的点,完成移动后要满足所有己方的点至少有一个士兵。问题要的是让边界点(与敌人占的点相邻的自己的点)中的最小值最大。
最小值最大,显然二分。然后就二分+网络流搞了。
值得说的是至少一个士兵的处理,可以直接对于各个点需要几个士兵向汇点连边,即边界点需要二分数值的士兵,而其他需要1个士兵;也可以一开始就把各点的士兵数都-1,也可以;或者最小费用最大流,不过画蛇添足。。
其实这题题目意思感觉不清晰,反正搞过样例就差不多能A了吧。。另外UVa上的样例有点问题,我上面改了。
代码
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 222
#define MAXM 222*222 struct Edge{
int v,cap,flow,next;
}edge[MAXM];
int vs,vt,NE,NV;
int head[MAXN]; void addEdge(int u,int v,int cap){
edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
edge[NE].next=head[v]; head[v]=NE++;
} int level[MAXN];
int gap[MAXN];
void bfs(){
memset(level,-1,sizeof(level));
memset(gap,0,sizeof(gap));
level[vt]=0;
gap[level[vt]]++;
queue<int> que;
que.push(vt);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(level[v]!=-1) continue;
level[v]=level[u]+1;
gap[level[v]]++;
que.push(v);
}
}
} int pre[MAXN];
int cur[MAXN];
int ISAP(){
bfs();
memset(pre,-1,sizeof(pre));
memcpy(cur,head,sizeof(head));
int u=pre[vs]=vs,flow=0,aug=INF;
gap[0]=NV;
while(level[vs]<NV){
bool flag=false;
for(int &i=cur[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
flag=true;
pre[v]=u;
u=v;
//aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
aug=min(aug,edge[i].cap-edge[i].flow);
if(v==vt){
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]){
edge[cur[u]].flow+=aug;
edge[cur[u]^1].flow-=aug;
}
//aug=-1;
aug=INF;
}
break;
}
}
if(flag) continue;
int minlevel=NV;
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==0) break;
level[u]=minlevel+1;
gap[level[u]]++;
u=pre[u];
}
return flow;
} int n,a[111];
char map[111][111]; bool isOK(int k){
vs=0; vt=2*n+1; NV=vt+1; NE=0;
memset(head,-1,sizeof(head));
int tot=0;
for(int i=1; i<=n; ++i){
if(a[i]==0) continue;
addEdge(vs,i,a[i]);
addEdge(i,i+n,INF); bool flag=0;
for(int j=1; j<=n; ++j){
if(map[i][j]=='N') continue;
if(a[j]==0) flag=1;
else addEdge(i,j+n,INF);
} if(flag){
addEdge(i+n,vt,k);
tot+=k;
}else{
addEdge(i+n,vt,1);
++tot;
}
}
return ISAP()==tot;
} int main(){
scanf("%*d");
while(~scanf("%d",&n)){
for(int i=1; i<=n; ++i){
scanf("%d",a+i);
}
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j){
scanf(" %c",&map[i][j]);
}
}
int l=0,r=111111;
while(l<r){
int mid=l+r+1>>1;
if(isOK(mid)) l=mid;
else r=mid-1;
}
printf("%d\n",l);
}
return 0;
}
UVa12264 Risk(最大流)的更多相关文章
- uva12264 Risk
最小值最大,就二分判断. map[i] = '0'+map[i];这样更方便 每个点拆成i,i’, S连i,cap为a[i],i’连T,cap为1(保证至少剩一个)或mid. i,i’ ,a[i] ...
- Risk UVA - 12264 拆点法+最大流+二分 最少流量的节点流量尽量多。
/** 题目:Risk UVA - 12264 链接:https://vjudge.net/problem/UVA-12264 题意:给n个点的无权无向图(n<=100),每个点有一个非负数ai ...
- uva 12264 Risk
https://vjudge.net/problem/UVA-12264 题意: 有很多个阵地,分为敌方和己方,每个士兵可以移动到相邻的己方的阵地,但是只能移动一步. 现在要让与敌方相邻的阵地中士兵最 ...
- 使用C#处理基于比特流的数据
使用C#处理基于比特流的数据 0x00 起因 最近需要处理一些基于比特流的数据,计算机处理数据一般都是以byte(8bit)为单位的,使用BinaryReader读取的数据也是如此,即使读取bool型 ...
- HTML 事件(三) 事件流与事件委托
本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...
- FILE文件流的中fopen、fread、fseek、fclose的使用
FILE文件流用于对文件的快速操作,主要的操作函数有fopen.fseek.fread.fclose,在对文件结构比较清楚时使用这几个函数会比较快捷的得到文件中具体位置的数据,提取对我们有用的信息,满 ...
- java.IO输入输出流:过滤流:buffer流和data流
java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? ...
- java 字节流与字符流的区别
字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢?实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作 ...
- BZOJ 3504: [Cqoi2014]危桥 [最大流]
3504: [Cqoi2014]危桥 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1407 Solved: 703[Submit][Status] ...
随机推荐
- python基础——单元测试
python基础——单元测试 如果你听说过“测试驱动开发”(TDD:Test-Driven Development),单元测试就不陌生. 单元测试是用来对一个模块.一个函数或者一个类来进行正确性检验的 ...
- 查看Linux分区格式
第一种方法: 使用mount [root@ol6-121-rac1 ~]# mount /dev/mapper/vg_ol6121rac1-lv_root on / type ext4 (rw) ...
- 6-03使用SQL语句一次型向表中插入多行数据
通过将现有表中的数据添加到已存在的表中: INSERT INTO <表名><列名> SELECT<列名> FROM<源表名> 将UserInfo的数据添 ...
- Reporting Services 的伸缩性和性能表现规划(转载)
简介 Microsoft? SQL Server? Reporting Services 是一个将集中管理的报告服务器具有的伸缩性和易管理性与基于 Web 和桌面的报告交付手段集于一身的报告平台.Re ...
- C# 拓展方法
/// <summary> /// 扩展类 /// </summary> public static class Extend { /// <summary> // ...
- I/O复用模型之select学习
linux下的I/O模型可以分为5种: 1.阻塞式I/O模型 2.非阻塞式I/O模型 3.I/O复用模型 4.信号驱动I/O模型 5.异步I/O模型 简单解释: 阻塞和非阻塞:就是说需要做一件事的时候 ...
- Java学习笔记(九)——继承
一.继承 1.概念: 继承是类于类之间的关系,是一种"is a "的关系 Ps: Java是单继承 2.优势: (1)子类直接拥有父类的所有属性和方法(除了privata) (2) ...
- indeterminateDrawable
Android原生控件只有横向进度条一种,而且没法变换样式,比如原生rom的样子很丑是吧,当伟大的产品设计要求更换前背景,甚至纵向,甚至圆弧状的,咋办,比如ok,我们开始吧: 一)变换前背景 先来看看 ...
- 如何修改 SQL Server 代理主作业 (Transact-SQL)
本主题介绍了如何使用存储过程修改 Microsoft SQL Server 代理主作业. 更改作业定义计划的详细信息 1. 执行 sp_update_schedule. 在作业中添加.更改 ...
- 【jQuery 冻结任意行列】冻结任意行和列的jQuery插件
实现原理: 创建多个div,div之间通过css实现层叠,每个div放置当前表格的克隆.例如:需要行冻结时,创建存放冻结行表格的div,通过设置z-index属性和position属性,让冻结行表格在 ...