1. /**
  2. 题目:Risk UVA - 12264
  3. 链接:https://vjudge.net/problem/UVA-12264
  4. 题意:给n个点的无权无向图(n<=100),每个点有一个非负数ai。
  5. 若ai==0则此点归敌方所有,若ai>0则此点归你且上面有ai个属于你的士兵。
  6. 保证至少有一个属于你的点与敌方的点相邻。你可以让你的每个士兵最多移动一次
  7. ,每次可以待在原地或者去到相邻的属于你的领地,但每个点至少要留1各士兵,
  8. 使得最薄弱的关口尽量坚固。关口是指与敌方点相邻的点,薄弱与坚固分别指兵少与兵多。
  9.  
  10. 思路:拆点法+最大流+二分。
  11.  
  12. 将点x,拆分成x,x'。
  13. s->x,容量为初始士兵数量。
  14. x'->t。 如果x是薄弱点,那么容量为mid,否则容量为1。1是为了满足题目至少留一个兵。
  15. x->x',容量为INF。
  16.  
  17. 如果x与y相邻,x->y',容量为INF。
  18.  
  19. 上面的容量为mid,就是假如所有的薄弱点都为mid个士兵,是否可行,如果可行,那么增加mid,找一个满足的最大的mid。
  20.  
  21. 二分mid。
  22.  
  23. 如果最大流=薄弱点数量*mid+(自己的领地结点数-薄弱点数量)*1。那么可行。
  24.  
  25. 注意:原题题意给出的输入输出要求是没有问题的,不过题目的实际输入输出有点问题。照着题意要求做就行。
  26.  
  27. */
  28. #include<iostream>
  29. #include<cstring>
  30. #include<vector>
  31. #include<map>
  32. #include<cstdio>
  33. #include<algorithm>
  34. #include<queue>
  35. using namespace std;
  36. const long long MAS = 1e13;
  37. const int INF = 0x3f3f3f3f;
  38. typedef long long LL;
  39. const int N = ;///拆点法,注意要乘以个2.
  40. struct Edge{
  41. int from, to, cap, flow;
  42. Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
  43. };
  44. struct Dinic{
  45. int n, m, s, t;
  46. vector<Edge> edges;
  47. vector<int> G[N];
  48. bool vis[N];
  49. int d[N];
  50. int cur[N];
  51.  
  52. void init(int n)
  53. {
  54. this->n = n;
  55. for(int i = ; i <= n; i++) G[i].clear();
  56. edges.clear();
  57. }
  58.  
  59. void AddEdge(int from,int to,int cap)
  60. {
  61. edges.push_back(Edge(from,to,cap,));
  62. edges.push_back(Edge(to,from,,));
  63. m = edges.size();
  64. G[from].push_back(m-);
  65. G[to].push_back(m-);
  66. }
  67.  
  68. bool BFS()
  69. {
  70. memset(vis, , sizeof vis);
  71. queue<int> Q;
  72. Q.push(s);
  73. d[s] = ;
  74. vis[s] = ;
  75. while(!Q.empty())
  76. {
  77. int x = Q.front();
  78. Q.pop();
  79. for(int i = ; i < G[x].size(); i++)
  80. {
  81. Edge &e = edges[G[x][i]];
  82. if(!vis[e.to]&&e.cap>e.flow)
  83. {
  84. vis[e.to] = ;
  85. d[e.to] = d[x]+;
  86. Q.push(e.to);
  87. }
  88. }
  89. }
  90. return vis[t];
  91. }
  92.  
  93. int DFS(int x,int a)
  94. {
  95. if(x==t||a==) return a;
  96. int flow = , f;
  97. for(int &i = cur[x]; i < G[x].size(); i++)
  98. {
  99. Edge& e = edges[G[x][i]];
  100. if(d[x]+==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>)
  101. {
  102. e.flow += f;
  103. edges[G[x][i]^].flow -= f;
  104. flow += f;
  105. a -= f;
  106. if(a==) break;
  107. }
  108. }
  109. return flow;
  110. }
  111.  
  112. int Maxflow(int s,int t)
  113. {
  114. this->s = s, this->t = t;
  115. int flow = ;
  116. while(BFS())
  117. {
  118. memset(cur, , sizeof cur);
  119. flow += DFS(s,INF);
  120. }
  121. return flow;
  122. }
  123. };
  124. char str[N][N];
  125. int sd[N], f[N][N];
  126. int weak[N], enemy[N];
  127. int main()
  128. {
  129. int n, k;
  130. cin>>k;
  131. while(k--){
  132. scanf("%d",&n);
  133. memset(enemy, , sizeof enemy);
  134. for(int i = ; i <= n; i++){
  135. scanf("%d",&sd[i]);
  136. if(sd[i]==) enemy[i] = ;///敌人结点
  137. }
  138. memset(f, , sizeof f);
  139. memset(weak, , sizeof weak);
  140. for(int i = ; i <= n; i++){
  141. scanf("%s",str[i]+);
  142. for(int j = ; j <= n; j++){
  143. if(str[i][j]=='Y'){
  144. f[i][j] = ;
  145. if(enemy[i]&&enemy[j]==){
  146. weak[j] = ;///薄弱结点
  147. }
  148. if(enemy[i]==&&enemy[j]){
  149. weak[i] = ;///薄弱结点
  150. }
  151. }
  152. }
  153. }
  154. int s = , t = n*+;
  155. Dinic dinic, save;
  156. dinic.init(t);
  157. for(int i = ; i <= n; i++){
  158. if(enemy[i]) continue;
  159. dinic.AddEdge(s,i,sd[i]);
  160. dinic.AddEdge(i,i+n,INF);
  161. if(weak[i]==){
  162. dinic.AddEdge(i+n,t,);
  163. }
  164. }
  165. for(int i = ; i <= n; i++){
  166. if(enemy[i]) continue;
  167. for(int j = ; j <= n; j++){
  168. if(enemy[j]) continue;
  169. if(f[i][j]){
  170. dinic.AddEdge(i,j+n,INF);
  171. }
  172. }
  173. }
  174.  
  175. save = dinic;
  176. int weaknum = , total = ;
  177. for(int i = ; i <= n; i++){
  178. if(weak[i]) weaknum++;
  179. if(enemy[i]==) total++;
  180. }
  181. int lo = , hi = INF, mid;
  182. int ans;
  183. while(lo<=hi){
  184. mid = (lo+hi)/;
  185. dinic = save;
  186. for(int i = ; i <= n; i++){
  187. if(weak[i]){
  188. dinic.AddEdge(i+n,t,mid);
  189. }
  190. }
  191. int mas = dinic.Maxflow(s,t);
  192. int sum = weaknum*mid+(total-weaknum);
  193. if(mas==sum){
  194. lo = mid+;
  195. ans = mid;
  196. }else
  197. {
  198. hi = mid-;
  199. }
  200. }
  201. printf("%d\n",ans);
  202. }
  203. return ;
  204. }

Risk UVA - 12264 拆点法+最大流+二分 最少流量的节点流量尽量多。的更多相关文章

  1. Acme Corporation UVA - 11613 拆点法+最大费用最大流(费用取相反数)+费用有正负

    /** 题目:Acme Corporation UVA - 11613 拆点法+最大费用最大流(费用取相反数)+费用有正负 链接:https://vjudge.net/problem/UVA-1161 ...

  2. UVa 1658 (拆点法 最小费用流) Admiral

    题意: 给出一个有向带权图,求从起点到终点的两条不相交路径使得权值和最小. 分析: 第一次听到“拆点法”这个名词. 把除起点和终点以外的点拆成两个点i和i',然后在这两点之间连一条容量为1,费用为0的 ...

  3. UVA 1658 海军上将(拆点法+最小费用限制流)

    海军上将 紫书P375 这题我觉得有2个难点: 一是拆点,要有足够的想法才能把这题用网络流建模,并且知道如何拆点. 二是最小费用限制流,最小费用最大流我们都会,但如果限制流必须为一个值呢?比如这题限制 ...

  4. poj3422 拆点法x->x'建立两条边+最小费用最大流

    /** 题目:poj3422 拆点法+最小费用最大流 链接:http://poj.org/problem?id=3422 题意:给定n*n的矩阵,含有元素值,初始sum=0.每次从最左上角开始出发,每 ...

  5. UVA1658 Admiral 拆点法解决结点容量(路径不能有公共点,容量为1的时候) 最小费用最大流

    /** 题目:UVA1658 Admiral 链接:https://vjudge.net/problem/UVA-1658 题意:lrj入门经典P375 求从s到t的两条不相交(除了s和t外,没有公共 ...

  6. 紫书 习题 11-4 UVa 1660 (网络流拆点法)

    这道题改了两天-- 因为这道题和节点有关, 所以就用拆点法解决节点的容量问题. 节点拆成两个点, 连一条弧容量为1, 表示只能经过一次. 然后图中的弧容量无限. 然后求最小割, 即最大流, 即为答案. ...

  7. uva 1658(最小费用最大流)

    题意:一个带权有向图,求起点到终点的两条路径权值之和最小,且两条路径没有公共点(除起点,终点): 分析:拆点法,将u拆成u和u',u-u'容量为1,费用为0,这样就能保证每个点只用一次,起点s-s'容 ...

  8. UVA1349 Optimal Bus Route Design 拆点法+最小费用最佳匹配

    /** 题目:UVA1349 Optimal Bus Route Design 链接:https://vjudge.net/problem/UVA-1349 题意:lrj入门经典P375 给n个点(n ...

  9. hdu4289 最小割最大流 (拆点最大流)

    最小割最大流定理:(参考刘汝佳p369)增广路算法结束时,令已标号结点(a[u]>0的结点)集合为S,其他结点集合为T=V-S,则(S,T)是图的s-t最小割. Problem Descript ...

随机推荐

  1. 线程局部存储(TLS)

    线程局部存储(TLS) 2011-10-11 09:59:28|  分类: Win32---API |  标签:tls   |举报 |字号 订阅   什么是线程局部存储 众所周知,线程是执行的单元,同 ...

  2. Win7双屏显示设置

    双显示器:一个是T410自己的屏幕,一个是宏基的Acer1296*768显示器. 连接:将宏基显示器的Display端子连接到笔记本的Display口上,电源接上. 设置过程: 1.右键点屏幕,选“S ...

  3. Netty利用ChannelGroup广播消息

    在Netty中提供了ChannelGroup接口,该接口继承Set接口,因此可以通过ChannelGroup可管理服务器端所有的连接的Channel,然后对所有的连接Channel广播消息. Serv ...

  4. PageRank学习

    喜欢手写学习,记忆深刻(字丑勿喷!). 计算过程的代码如下: public class PageRank { private static double m[][]={ { 0 , 0.5 , 1 , ...

  5. webDriver API——第15部分Expected conditions Support

    class selenium.webdriver.support.expected_conditions.alert_is_present Bases: object Expect an alert ...

  6. 微信小程序小红点未读消息如何实现?

      如图类似的 这样的需求还挺多的,那么如何实现呢? data: { userInfo: {}, projectSource: 'https://github.com/liuxuanqiang/wec ...

  7. android 总结

    两点说明:  1. 本文我的老大推荐给的, 我自己之前也写过自学的帖子, 现在看看感觉不是很完整, 故转载此篇 2. 本文最后附有<android讲义 第二版> 下载地址, 我个人认为最适 ...

  8. malloc、calloc、realloc的区别(转)

    (1)C语言跟内存分配方式 <1>从静态存储区域分配.       内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量.static变量.<2> ...

  9. 关于vector push_back()与其他方式读取数据的效率对比(转)

    引言: 在读取大量数据(数组)时,使用vector会尽量保证不会炸空间(MLE),但是相比于scanf的读取方式会慢上不少.但到底效率相差有多大,我们将通过对比测试得到结果. 测试数据:利用srand ...

  10. CopyOnWriteArrayList操作java.lang.UnsupportedOperationException

    问题一:CopyOnWriteArrayList不能强制转换成ArrayList 解决的方法:将CopyOnWriteArrayList传入ArrayList中 ArrayList<T> ...