UVALive 4949 Risk(二分网络流、SAP)

n个区域,每个区域有我方军队a[i],a[i]==0的区域表示敌方区域,输入邻接矩阵。问经过一次调兵,使得我方边界处(与敌军区域邻接的区域)士兵的最小值最大。输出该最大值。调兵从i->j仅当a[i]>0&&a[j]>0&&adj[i][j]==true;感觉有点像玩三国志什么的。。。

赛后才知道是网络流。。网络流的构图真妙。。。给我方建个超级基地,然后把敌方的区域合并成汇点。。

从超级基地连一条边到我方所有区域,流量为a[i]-1,限流该区域的答案,然后i->i+n,流量为a[i],用于可能的分配士兵,还有就是i+n->j(a[i]&&a[j]&&adj[i][j]),流量为inf。。。然后再把所有我方的边界区域连到汇点i->T(isBorder[i])。。。这个流量应该就是答案了。。。

所有正解就是,二分流量答案,SAP检查之。。。

  1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4 #include <algorithm>
5 #include <cmath>
6 #include <string>
7 #include <vector>
8 #include <queue>
9 #include <set>
10 using namespace std;
11
12 #define ll long long
13 #define inf 2100000000
14 #define eps 1e-8
15 #define mn 505
16 #define me 200005
17
18 int dis[mn], pre[mn], gap[mn], arc[mn], f[me], cap[me];
19 int first[mn], nxt[me], vv[me], e;
20
21 inline void add(int u,int v,int c) {
22 vv[e] = v, cap[e] = c, nxt[e] = first[u], first[u] = e++;
23 vv[e] = u, cap[e] = 0, nxt[e] = first[v], first[v] = e++;
24 }
25 int sap( int s, int t, int n ) {
26 int q[mn], j, mindis, ans = 0, head = 0, tail = 1, u, v, low;
27 bool found, vis[mn];
28 memset( dis, 0, sizeof(dis) );
29 memset( gap, 0, sizeof(gap) );
30 memset( vis, 0, sizeof(vis) );
31 memset( arc, -1, sizeof(arc) );
32 memset( f, 0, sizeof(f) );
33 q[0] = t; vis[t] = true; dis[t] = 0; gap[0] = 1;
34 while( head < tail ) {
35 u = q[head++];
36 for( int i = first[u]; i != -1; i = nxt[i] ) {
37 v = vv[i];
38 if( !vis[v] ) {
39 dis[v] = dis[u] + 1;
40 vis[v] = true;
41 q[tail++] = v;
42 gap[dis[v]]++;
43 arc[v] = first[v];
44 }
45 }
46 }
47 u = s; low = inf; pre[s] = s;
48 while( dis[s] < n ) {
49 found = false;
50 for( int &i = arc[u]; i != -1; i = nxt[i] )
51 if( dis[vv[i]] == dis[u]-1 && cap[i] > f[i] ) {
52 found = true; v = vv[i];
53 low = low < cap[i] - f[i] ? low : cap[i] - f[i];
54 pre[v] = u; u = v;
55 if( u == t ) {
56 while( u != s ) {
57 u = pre[u];
58 f[arc[u]] += low;
59 f[arc[u]^1] -= low;
60 }
61 ans += low; low = inf;
62 }
63 break;
64 }
65 if( found )
66 continue;
67 mindis = n;
68 for(int i = first[u]; i != -1; i = nxt[i] ) {
69 if( mindis > dis[vv[i]] && cap[i] > f[i] ) {
70 mindis = dis[vv[j = i]];
71 arc[u] = i;
72 }
73 }
74 gap[dis[u]]--;
75 if( gap[dis[u]] == 0 )
76 return ans;
77 dis[u] = mindis + 1;
78 gap[dis[u]]++;
79 u = pre[u];
80 }
81 return ans;
82 }
83
84 char ch[111][111];
85 bool border[mn];
86 int a[111];
87 int getborder(int n){
88 memset(border,false,sizeof(border));
89 for(int i=1;i<=n;++i){
90 if(a[i]==0)
91 for(int j=1;j<=n;++j)
92 if(a[j]&&ch[i][j]==‘Y‘)border[j]=true;
93 }
94 int ret=0;
95 for(int i=1;i<=n;++i)ret+=border[i];
96 return ret;
97 }
98 void build(int cap,int n){
99 memset(first,-1,sizeof(first));e=0;
100 for(int i=1;i<=n;++i)if(a[i])add(2*n+1,i,a[i]-1),add(i,i+n,a[i]);
101 for(int i=1;i<=n;++i)
102 for(int j=i+1;j<=n;++j)
103 if(ch[i][j]==‘Y‘&&a[i]&&a[j])
104 add(i+n,j,inf),add(j+n,i,inf);
105 for(int i=1;i<=n;++i)if(border[i])add(i,2*n+2,cap);
106 }
107 int main(){
108 int t;
109 scanf("%d",&t);
110 while(t--){
111 int n;
112 scanf("%d",&n);
113 for(int i=1;i<=n;++i)scanf("%d",a+i);
114 for(int i=1;i<=n;++i)scanf("%s",ch[i]+1);
115 int cnt=getborder(n);
116 int l=0,r=10000;
117 while(l<r){
118 int mid=(l+r+1)/2;
119 build(mid,n);
120 if(sap(2*n+1,2*n+2,2*n+2)!=cnt*mid)r=mid-1;
121 else l=mid;
122 }
123 printf("%d\n",l+1);
124 }
125 return 0;
126 }

时间: 2024-10-29 19:07:01

UVALive 4949 Risk(二分网络流、SAP)的相关文章

POJ 2391 Ombrophobic Bovines (二分,最短路径,网络流sap,dinic,预留推进 )

Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14019   Accepted: 3068 Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in their hooves. They h

POJ 2455 Secret Milking Machine(搜索-二分,网络流-最大流)

Secret Milking Machine Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9658   Accepted: 2859 Description Farmer John is constructing a new milking machine and wishes to keep it secret as long as possible. He has hidden in it deep within

hihoCoder 1389 Sewage Treatment 【二分+网络流+优化】 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2016)网络赛)

#1389 : Sewage Treatment 时间限制:2000ms 单点时限:2000ms 内存限制:256MB 描述 After years of suffering, people could not tolerate the pollution in the city any more, and started a long-lasting protest. Eventually, the municipal government made up its mind to deal w

POJ 2455Secret Milking Machine(二分+网络流之最大流)

题目地址:POJ2455 手残真浪费时间啊..又拖到了今天才找出了错误..每晚两道题不知不觉又变回了每晚一道题...sad.. 第一次在isap中忘记调用bfs,第二次则是遍历的时候居然是从1开始遍历的...sad... 这题思路倒是很简单,就是有一个比较坑的地方,就是这里的重边要当两条边来用,以前受最短路什么的影响,直接把慢的删了,很明显不对...这里的两条重边都是可以走的. 建图思路是,将1当作源点,将n当作汇点.右边的地方就连边,注意是无向边.最后判断最大流是否等于道路条数.二分找最小值.

【bzoj1822】[JSOI2010]Frozen Nova 冷冻波 计算几何+二分+网络流最大流

题目描述 WJJ喜欢“魔兽争霸”这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没有被树木阻挡(也就是说,巫妖和小精灵的连线与任何树木都没有公共点)的话,巫妖就可以瞬间杀灭一个小精灵. 在森林里有N个巫妖,每个巫妖释放Frozen Nova之后,都需要等待一段时间,才能再次施放.不同的巫妖有不同的等待时间和施法范围,但相同的是,每次施放都可以

【bzoj1733】[Usaco2005 feb]Secret Milking Machine 神秘的挤奶机 二分+网络流最大流

题目描述 Farmer John is constructing a new milking machine and wishes to keep it secret as long as possible. He has hidden in it deep within his farm and needs to be able to get to the machine without being detected. He must make a total of T (1 <= T <=

UVA 12124 UVAlive 3971 Assemble(二分 + 贪心)

先从中找出性能最好的那个数, 在用钱比较少的去组合,能组出来就表明答案在mid的右边,反之在左边, #include<string.h> #include<map> #include<stdio.h> #include<iostream> #include<algorithm> using namespace std; map<string,int> vic;//以字符映射数字 int end,start; int num; int

【bzoj3130】[Sdoi2013]费用流 二分+网络流最大流

题目描述 Alice和Bob做游戏,给出一张有向图表示运输网络,Alice先给Bob一种最大流方案,然后Bob在所有边上分配总和等于P的非负费用.Alice希望总费用尽量小,而Bob希望总费用尽量大.求两人都采取最优策略的情况下最大流及总费用. 输入 第一行三个整数N,M,P.N表示给定运输网络中节点的数量,M表示有向边的数量,P的含义见问题描述部分.为了简化问题,我们假设源点S是点1,汇点T是点N.接下来M行,每行三个整数A,B,C,表示有一条从点A到点B的有向边,其最大流量是C. 输出 第一

HDU 3081 Marriage Match II 二分 + 网络流

Marriage Match II 题意:有n个男生,n个女生,现在有 f 条男生女生是朋友的关系, 现在有 m 条女生女生是朋友的关系, 朋友的朋友是朋友,现在进行 k 轮游戏,每轮游戏都要男生和女生配对,每轮配对过的人在接下来中都不能配对,求这个k最大是多少. 题解:二分 + 网络流check . 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt",