题目

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(最大流)的更多相关文章

  1. uva12264 Risk

    最小值最大,就二分判断. map[i] = '0'+map[i];这样更方便 每个点拆成i,i’,  S连i,cap为a[i],i’连T,cap为1(保证至少剩一个)或mid. i,i’ ,a[i] ...

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

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

  3. uva 12264 Risk

    https://vjudge.net/problem/UVA-12264 题意: 有很多个阵地,分为敌方和己方,每个士兵可以移动到相邻的己方的阵地,但是只能移动一步. 现在要让与敌方相邻的阵地中士兵最 ...

  4. 使用C#处理基于比特流的数据

    使用C#处理基于比特流的数据 0x00 起因 最近需要处理一些基于比特流的数据,计算机处理数据一般都是以byte(8bit)为单位的,使用BinaryReader读取的数据也是如此,即使读取bool型 ...

  5. HTML 事件(三) 事件流与事件委托

    本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...

  6. FILE文件流的中fopen、fread、fseek、fclose的使用

    FILE文件流用于对文件的快速操作,主要的操作函数有fopen.fseek.fread.fclose,在对文件结构比较清楚时使用这几个函数会比较快捷的得到文件中具体位置的数据,提取对我们有用的信息,满 ...

  7. java.IO输入输出流:过滤流:buffer流和data流

    java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? ...

  8. java 字节流与字符流的区别

    字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢?实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作 ...

  9. BZOJ 3504: [Cqoi2014]危桥 [最大流]

    3504: [Cqoi2014]危桥 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1407  Solved: 703[Submit][Status] ...

随机推荐

  1. [Android Pro] Android下toolbox简介

    toolbox是Android 自带的提供shell命令的软件.有点类似于busybox,但功能上好像弱很多.其源码可以从Android source code 中system/core/toolbo ...

  2. IE11 的区别

    http://msdn.microsoft.com/zh-tw/visualc/bg182625

  3. HBase参数配置及说明(转)

    版本:0.94-cdh4.2.1 hbase-site.xml配置 hbase.tmp.dir 本地文件系统tmp目录,一般配置成local模式的设置一下,但是最好还是需要设置一下,因为很多文件都会默 ...

  4. 【JAVA集合框架之工具类】

    一.概述 JAVA集合框架中有两个很重要的工具类,一个是Collections,另一个是Arrays.分别封装了对集合的操作方法和对数组的操作方法,这些操作方法使得程序员的开发更加高效. public ...

  5. 攻城狮在路上(壹) Hibernate(三)--- 属性访问、命名策略、派生属性、指定包名等

    一.hibernate访问持久化类属性的策略: 在<property>元素中的access属性用于指定Hibernate访问持久化类属性的方式. 常见的方式如下: 1.property:默 ...

  6. Oracle【IT实验室】数据库备份与恢复之四:RMAN(备份与恢复管理器)

    RMAN是ORACLE提供的一个备份与恢复的工具,可以用来备份和还原数据库文件. 归档日志和控制文件.它也可以用来执行完全或不完全的数据库恢复. RMAN可以由命令行接口或者 OEM的 Backup ...

  7. jquery获取radio和select选中值

    //jquery 获取radio选中值 <input type="radio" name="c_type" value="a" > ...

  8. php几个常用的概率算法(抽奖、广告首选)

    做网站类的有时会弄个活动什么的,来让用户参加,既吸引用户注册,又提高网站的用户活跃度.同时参加的用户会获得一定的奖品,有100%中奖的,也有按一定概率中奖的,大的比如中个ipad.iphone5,小的 ...

  9. Macbook Pro安装win7

    1.进入OS X系统,在实用工具中打开Boot Camp助理 2.用磁盘工具对磁盘进行分区,将需要安装win7的分区格式化成FAT格式 3.用Boot Camp对磁盘进行分割,然后插入win7的安装光 ...

  10. 跟着鸟哥学Linux系列笔记1

    跟着鸟哥学Linux系列笔记0-扫盲之概念 跟着鸟哥学Linux系列笔记0-如何解决问题 装完linux之后,接下来一步就是进行相关命令的学习了 第五章:首次登录与在线求助man page 1. X ...