题目

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. java获取短uuid

    public static String[] chars = new String[] { "a", "b", "c", "d&q ...

  2. 3.2 STL中的函数对象类模板

    *: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...

  3. 1.1 STL 概述

    综述   STL = Standard Template Library,标准模板库,惠普实验室开发的一系列软件的统称.它是由Alexander Stepanov.Meng Lee和David R M ...

  4. JavaScript基础——创建函数

    JavaScript的最重要的一个部分是制作其他代码可以重用的代码.要做到这一点,你可以把代码组织成执行特定任务的函数.函数是结合在一个单一的块中,并给予一个名称的一系列代码语句.然后,你就可以通过引 ...

  5. C语言的OOP实践(OOC)

    OOC 面向对象 C 语言编程实践 - 文章 - 伯乐在线http://blog.jobbole.com/105105/ ---硬着头皮看完了,但是感觉还是抽象有不理解的地方,感觉用C实现OOP好难啊 ...

  6. SQL脚本书写的几点建议

    1.索引很关键,创建合理的索引,提升查询速度:            DBCC FREEPORCCACHE       DBCC DROPCLEANBUFFERS                    ...

  7. 【stut 逆置正整数】

    C语言实验——逆置正整数 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 输入一个三位正整数,将它反向输出. 输入 3位正整数. ...

  8. dblink

    drop database link "STANDARD"; drop database link "CSPS"   --创建dblink create dat ...

  9. 攻城狮在路上(壹) Hibernate(一)--- 软件环境、参考书目等一览表

    1.环境配置: web容器:tomcat6.0 JDK:1.7.0_51 hibernate:4.2.0.Final 操作系统:WIN8 64位 数据库:mysql  Ver 14.12 Distri ...

  10. Python多版本共存之pyenv

    经常遇到这样的情况: 系统自带的Python是2.6,自己需要Python 2.7中的某些特性: 系统自带的Python是2.x,自己需要Python 3.x: 此时需要在系统中安装多个Python, ...