Risk UVA - 12264 拆点法+最大流+二分 最少流量的节点流量尽量多。
- /**
- 题目:Risk UVA - 12264
- 链接:https://vjudge.net/problem/UVA-12264
- 题意:给n个点的无权无向图(n<=100),每个点有一个非负数ai。
- 若ai==0则此点归敌方所有,若ai>0则此点归你且上面有ai个属于你的士兵。
- 保证至少有一个属于你的点与敌方的点相邻。你可以让你的每个士兵最多移动一次
- ,每次可以待在原地或者去到相邻的属于你的领地,但每个点至少要留1各士兵,
- 使得最薄弱的关口尽量坚固。关口是指与敌方点相邻的点,薄弱与坚固分别指兵少与兵多。
- 思路:拆点法+最大流+二分。
- 将点x,拆分成x,x'。
- s->x,容量为初始士兵数量。
- x'->t。 如果x是薄弱点,那么容量为mid,否则容量为1。1是为了满足题目至少留一个兵。
- x->x',容量为INF。
- 如果x与y相邻,x->y',容量为INF。
- 上面的容量为mid,就是假如所有的薄弱点都为mid个士兵,是否可行,如果可行,那么增加mid,找一个满足的最大的mid。
- 二分mid。
- 如果最大流=薄弱点数量*mid+(自己的领地结点数-薄弱点数量)*1。那么可行。
- 注意:原题题意给出的输入输出要求是没有问题的,不过题目的实际输入输出有点问题。照着题意要求做就行。
- */
- #include<iostream>
- #include<cstring>
- #include<vector>
- #include<map>
- #include<cstdio>
- #include<algorithm>
- #include<queue>
- using namespace std;
- const long long MAS = 1e13;
- const int INF = 0x3f3f3f3f;
- typedef long long LL;
- const int N = ;///拆点法,注意要乘以个2.
- struct Edge{
- int from, to, cap, flow;
- Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
- };
- struct Dinic{
- int n, m, s, t;
- vector<Edge> edges;
- vector<int> G[N];
- bool vis[N];
- int d[N];
- int cur[N];
- void init(int n)
- {
- this->n = n;
- for(int i = ; i <= n; i++) G[i].clear();
- edges.clear();
- }
- void AddEdge(int from,int to,int cap)
- {
- edges.push_back(Edge(from,to,cap,));
- edges.push_back(Edge(to,from,,));
- m = edges.size();
- G[from].push_back(m-);
- G[to].push_back(m-);
- }
- bool BFS()
- {
- memset(vis, , sizeof vis);
- queue<int> Q;
- Q.push(s);
- d[s] = ;
- vis[s] = ;
- while(!Q.empty())
- {
- int x = Q.front();
- Q.pop();
- for(int i = ; i < G[x].size(); i++)
- {
- Edge &e = edges[G[x][i]];
- if(!vis[e.to]&&e.cap>e.flow)
- {
- vis[e.to] = ;
- d[e.to] = d[x]+;
- Q.push(e.to);
- }
- }
- }
- return vis[t];
- }
- int DFS(int x,int a)
- {
- if(x==t||a==) return a;
- int flow = , f;
- for(int &i = cur[x]; i < G[x].size(); i++)
- {
- Edge& e = edges[G[x][i]];
- if(d[x]+==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>)
- {
- e.flow += f;
- edges[G[x][i]^].flow -= f;
- flow += f;
- a -= f;
- if(a==) break;
- }
- }
- return flow;
- }
- int Maxflow(int s,int t)
- {
- this->s = s, this->t = t;
- int flow = ;
- while(BFS())
- {
- memset(cur, , sizeof cur);
- flow += DFS(s,INF);
- }
- return flow;
- }
- };
- char str[N][N];
- int sd[N], f[N][N];
- int weak[N], enemy[N];
- int main()
- {
- int n, k;
- cin>>k;
- while(k--){
- scanf("%d",&n);
- memset(enemy, , sizeof enemy);
- for(int i = ; i <= n; i++){
- scanf("%d",&sd[i]);
- if(sd[i]==) enemy[i] = ;///敌人结点
- }
- memset(f, , sizeof f);
- memset(weak, , sizeof weak);
- for(int i = ; i <= n; i++){
- scanf("%s",str[i]+);
- for(int j = ; j <= n; j++){
- if(str[i][j]=='Y'){
- f[i][j] = ;
- if(enemy[i]&&enemy[j]==){
- weak[j] = ;///薄弱结点
- }
- if(enemy[i]==&&enemy[j]){
- weak[i] = ;///薄弱结点
- }
- }
- }
- }
- int s = , t = n*+;
- Dinic dinic, save;
- dinic.init(t);
- for(int i = ; i <= n; i++){
- if(enemy[i]) continue;
- dinic.AddEdge(s,i,sd[i]);
- dinic.AddEdge(i,i+n,INF);
- if(weak[i]==){
- dinic.AddEdge(i+n,t,);
- }
- }
- for(int i = ; i <= n; i++){
- if(enemy[i]) continue;
- for(int j = ; j <= n; j++){
- if(enemy[j]) continue;
- if(f[i][j]){
- dinic.AddEdge(i,j+n,INF);
- }
- }
- }
- save = dinic;
- int weaknum = , total = ;
- for(int i = ; i <= n; i++){
- if(weak[i]) weaknum++;
- if(enemy[i]==) total++;
- }
- int lo = , hi = INF, mid;
- int ans;
- while(lo<=hi){
- mid = (lo+hi)/;
- dinic = save;
- for(int i = ; i <= n; i++){
- if(weak[i]){
- dinic.AddEdge(i+n,t,mid);
- }
- }
- int mas = dinic.Maxflow(s,t);
- int sum = weaknum*mid+(total-weaknum);
- if(mas==sum){
- lo = mid+;
- ans = mid;
- }else
- {
- hi = mid-;
- }
- }
- printf("%d\n",ans);
- }
- return ;
- }
Risk UVA - 12264 拆点法+最大流+二分 最少流量的节点流量尽量多。的更多相关文章
- Acme Corporation UVA - 11613 拆点法+最大费用最大流(费用取相反数)+费用有正负
/** 题目:Acme Corporation UVA - 11613 拆点法+最大费用最大流(费用取相反数)+费用有正负 链接:https://vjudge.net/problem/UVA-1161 ...
- UVa 1658 (拆点法 最小费用流) Admiral
题意: 给出一个有向带权图,求从起点到终点的两条不相交路径使得权值和最小. 分析: 第一次听到“拆点法”这个名词. 把除起点和终点以外的点拆成两个点i和i',然后在这两点之间连一条容量为1,费用为0的 ...
- UVA 1658 海军上将(拆点法+最小费用限制流)
海军上将 紫书P375 这题我觉得有2个难点: 一是拆点,要有足够的想法才能把这题用网络流建模,并且知道如何拆点. 二是最小费用限制流,最小费用最大流我们都会,但如果限制流必须为一个值呢?比如这题限制 ...
- poj3422 拆点法x->x'建立两条边+最小费用最大流
/** 题目:poj3422 拆点法+最小费用最大流 链接:http://poj.org/problem?id=3422 题意:给定n*n的矩阵,含有元素值,初始sum=0.每次从最左上角开始出发,每 ...
- UVA1658 Admiral 拆点法解决结点容量(路径不能有公共点,容量为1的时候) 最小费用最大流
/** 题目:UVA1658 Admiral 链接:https://vjudge.net/problem/UVA-1658 题意:lrj入门经典P375 求从s到t的两条不相交(除了s和t外,没有公共 ...
- 紫书 习题 11-4 UVa 1660 (网络流拆点法)
这道题改了两天-- 因为这道题和节点有关, 所以就用拆点法解决节点的容量问题. 节点拆成两个点, 连一条弧容量为1, 表示只能经过一次. 然后图中的弧容量无限. 然后求最小割, 即最大流, 即为答案. ...
- uva 1658(最小费用最大流)
题意:一个带权有向图,求起点到终点的两条路径权值之和最小,且两条路径没有公共点(除起点,终点): 分析:拆点法,将u拆成u和u',u-u'容量为1,费用为0,这样就能保证每个点只用一次,起点s-s'容 ...
- UVA1349 Optimal Bus Route Design 拆点法+最小费用最佳匹配
/** 题目:UVA1349 Optimal Bus Route Design 链接:https://vjudge.net/problem/UVA-1349 题意:lrj入门经典P375 给n个点(n ...
- hdu4289 最小割最大流 (拆点最大流)
最小割最大流定理:(参考刘汝佳p369)增广路算法结束时,令已标号结点(a[u]>0的结点)集合为S,其他结点集合为T=V-S,则(S,T)是图的s-t最小割. Problem Descript ...
随机推荐
- 线程局部存储(TLS)
线程局部存储(TLS) 2011-10-11 09:59:28| 分类: Win32---API | 标签:tls |举报 |字号 订阅 什么是线程局部存储 众所周知,线程是执行的单元,同 ...
- Win7双屏显示设置
双显示器:一个是T410自己的屏幕,一个是宏基的Acer1296*768显示器. 连接:将宏基显示器的Display端子连接到笔记本的Display口上,电源接上. 设置过程: 1.右键点屏幕,选“S ...
- Netty利用ChannelGroup广播消息
在Netty中提供了ChannelGroup接口,该接口继承Set接口,因此可以通过ChannelGroup可管理服务器端所有的连接的Channel,然后对所有的连接Channel广播消息. Serv ...
- PageRank学习
喜欢手写学习,记忆深刻(字丑勿喷!). 计算过程的代码如下: public class PageRank { private static double m[][]={ { 0 , 0.5 , 1 , ...
- webDriver API——第15部分Expected conditions Support
class selenium.webdriver.support.expected_conditions.alert_is_present Bases: object Expect an alert ...
- 微信小程序小红点未读消息如何实现?
如图类似的 这样的需求还挺多的,那么如何实现呢? data: { userInfo: {}, projectSource: 'https://github.com/liuxuanqiang/wec ...
- android 总结
两点说明: 1. 本文我的老大推荐给的, 我自己之前也写过自学的帖子, 现在看看感觉不是很完整, 故转载此篇 2. 本文最后附有<android讲义 第二版> 下载地址, 我个人认为最适 ...
- malloc、calloc、realloc的区别(转)
(1)C语言跟内存分配方式 <1>从静态存储区域分配. 内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量.static变量.<2> ...
- 关于vector push_back()与其他方式读取数据的效率对比(转)
引言: 在读取大量数据(数组)时,使用vector会尽量保证不会炸空间(MLE),但是相比于scanf的读取方式会慢上不少.但到底效率相差有多大,我们将通过对比测试得到结果. 测试数据:利用srand ...
- CopyOnWriteArrayList操作java.lang.UnsupportedOperationException
问题一:CopyOnWriteArrayList不能强制转换成ArrayList 解决的方法:将CopyOnWriteArrayList传入ArrayList中 ArrayList<T> ...