1565: [NOI2009]植物大战僵尸

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1972  Solved: 917
[Submit][Status][Discuss]

Description

Input

Output

仅包含一个整数,表示可以获得的最大能源收入。注意,你也可以选择不进行任何攻击,这样能源收入为0。

Sample Input

3 2
10 0
20 0
-10 0
-5 1 0 0
100 1 2 1
100 0

Sample Output

25

HINT

在样例中, 植物P1,1可以攻击位置(0,0), P2, 0可以攻击位置(2,1)。 
一个方案为,首先进攻P1,1, P0,1,此时可以攻击P0,0 。共得到能源收益为(-5)+20+10 = 25。注意, 位置(2,1)被植物P2,0保护,所以无法攻击第2行中的任何植物。 
【大致数据规模】
约20%的数据满足1 ≤ N, M ≤ 5;
约40%的数据满足1 ≤ N, M ≤ 10;
约100%的数据满足1 ≤ N ≤ 20,1 ≤ M ≤ 30,-10000 ≤ Score ≤ 10000 。

Source

Solution

一开始想到的是,在网格图上加限制然后搞搞,发现其实不对,因为能吃掉的植物和网格什么的无关,而是和植物们的攻击有关

很容易想到,如果一个植物被另一个植物保护,那么必须吃掉另一个植物,才能吃掉这个植物,所以,很显然顺序是需要考虑的,但又发现,如果多个植物可以互相保护(也就是连成环,很显然这些植物都是无敌的RMB玩家)

这种类型很容易就联想到最小割模型(最大权闭合子图),又因为环上植物无敌,所以不去考虑环上植物,那么把环上的扔掉即可

开始想写Tarjan,写完后发现不行,于是换拓扑排序,然后发现太久太久没写过了,竟然快忘了....

这里可以直接建网络流图,拓扑一遍,在增广的时候加限制即可.(不过需要一些特殊的技巧)

或者先对保护的点连边,拓扑一遍,然后再建新图跑网络流即可 值得注意的是:保护的点需要加上它左边的点(很显然僵尸不能跳过一个植物吃后面的)

Code

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<algorithm>
  6. #include<vector>
  7. #include<queue>
  8. #include<stack>
  9. using namespace std;
  10. int read()
  11. {
  12. int x=,f=; char ch=getchar();
  13. while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
  14. while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
  15. return x*f;
  16. }
  17. #define maxn 1000
  18. #define maxm 1000010
  19. int n,m,total,score[maxn];
  20. struct EdgeNode{int next,to,cap;}edge[maxm];
  21. int head[maxn],cnt=;
  22. void addedge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;}
  23. void insertedge(int u,int v,int w) {addedge(u,v,w); addedge(v,u,);}
  24.  
  25. struct RoadNode{int next,to;}road[maxm>>];
  26. int last[maxn],tot;
  27. void addroad(int u,int v) {tot++; road[tot].next=last[u]; last[u]=tot; road[tot].to=v;}
  28. void insertroad(int u,int v) {addroad(u,v);}
  29. bool visit[maxn]; int du[maxn],s,t;
  30. void Paint(int now)
  31. {
  32. visit[now]=;
  33. for (int i=last[now]; i; i=road[i].next)
  34. if (!visit[road[i].to]) Paint(road[i].to);
  35. }
  36. void TopoSort()
  37. {
  38. s=,t=n*m;
  39. stack<int>st;
  40. for (int i=s; i<=t; i++) if (!du[i]) st.push(i); else visit[i]=;
  41. while (!st.empty())
  42. {
  43. int now=st.top(); st.pop(); visit[now]=;
  44. for (int i=last[now]; i; i=road[i].next)
  45. {
  46. du[road[i].to]--;
  47. if (!du[road[i].to]) st.push(road[i].to);
  48. }
  49. //printf("%d\n",now);
  50. }
  51. for (int i=s; i<=t; i++) if (visit[i]) Paint(i);
  52. }
  53. int dis[maxn],cur[maxn],S,T;
  54. #define inf 0x7fffffff
  55. bool bfs()
  56. {
  57. queue<int>q;
  58. for (int i=S; i<=T; i++) dis[i]=-;
  59. q.push(S); dis[S]=;
  60. while (!q.empty())
  61. {
  62. int now=q.front(); q.pop();
  63. for (int i=head[now]; i; i=edge[i].next)
  64. if (edge[i].cap && dis[edge[i].to]==-)
  65. dis[edge[i].to]=dis[now]+,q.push(edge[i].to);
  66. }
  67. return dis[T]!=-;
  68. }
  69. int dfs(int loc,int low)
  70. {
  71. if (loc==T) return low;
  72. int w,used=;
  73. for (int i=cur[loc]; i; i=edge[i].next)
  74. if (edge[i].cap && dis[edge[i].to]==dis[loc]+)
  75. {
  76. w=dfs(edge[i].to,min(low-used,edge[i].cap));
  77. edge[i].cap-=w; edge[i^].cap+=w; used+=w;
  78. if (used==low) return low; if (edge[i].cap) cur[loc]=i;
  79. }
  80. if (!used) dis[loc]=-;
  81. return used;
  82. }
  83. int dinic()
  84. {
  85. int tmp=;
  86. while (bfs())
  87. {
  88. for (int i=S; i<=T; i++) cur[i]=head[i];
  89. tmp+=dfs(S,inf);
  90. }
  91. return tmp;
  92. }
  93. void Build()
  94. {
  95. S=,T=n*m+;
  96. for (int i=; i<=n*m; i++)
  97. if (!visit[i])
  98. {
  99. if (score[i]>) insertedge(i,T,score[i]); else insertedge(S,i,-score[i]);
  100. for (int j=last[i]; j; j=road[j].next)
  101. if (!visit[road[j].to]) insertedge(i,road[j].to,inf);
  102. total+=score[i]>?score[i]:;
  103. }
  104. }
  105. int locate(int x,int y) {return (x-)*m+y;}
  106. int main()
  107. {
  108. n=read(),m=read();
  109. for (int i=; i<=n; i++)
  110. for (int j=; j<=m; j++)
  111. {
  112. int now=locate(i,j),num;
  113. score[now]=read(); num=read();
  114. for (int x,y,k=; k<=num; k++)
  115. x=read()+,y=read()+,insertroad(now,locate(x,y)),du[locate(x,y)]++;
  116. if (j>) insertroad(now,locate(i,j-)),du[locate(i,j-)]++;
  117. }
  118. TopoSort();
  119. Build();
  120. int maxflow=dinic();// printf("%d %d\n",total,maxflow);
  121. printf("%d\n",total-maxflow);
  122. return ;
  123. }

一写这种需要重构图的,用上road啊last,tot啊什么的,总会莫名其妙的写混...还要肉眼对拍浪费时间

【BZOJ-1565】植物大战僵尸 拓扑排序 + 最小割的更多相关文章

  1. P2805 [NOI2009]植物大战僵尸 (拓扑排序 + 最小割)

    题意:N*M的矩阵 每个点上都有一颗植物 僵尸只能从每一行的最右边向左进攻 每个植物有攻击范围 可以保护在攻击范围内的植物 同时每一颗植物也保护他左边的植物 摧毁每个植物能获得价值 如果这个植物被保护 ...

  2. BZOJ 1565 植物大战僵尸(拓扑排序+最大权闭合子图)

    图中的保护关系就类似于最大权闭合子图.即你想杀x,你就一定要杀掉保护x的点,那么把x向保护它的点连边.那么题目就转化成了最大权闭合子图的问题. 但是这个图有点特殊啊... 考虑有环的情况,显然这个环以 ...

  3. 洛谷2805 [NOI2009]植物大战僵尸 (拓扑排序+最小割)

    坚决抵制长题面的题目! 首先观察到这个题目中,我们会发现,我们对于原图中的保护关系(一个点右边的点对于这个点也算是保护) 相当于一种依赖. 那么不难看出这个题实际上是一个最大权闭合子图模型. 我们直接 ...

  4. BZOJ 1565 植物大战僵尸(最大权闭合图)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1565 题意:植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性: ...

  5. BZOJ 1565 植物大战僵尸 最大权闭合子图+网络流

    题意: 植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性: (1)价值: (2)保护集合,也就是这个植物可以保护矩阵中的某些格子. 现在你是僵尸,你每次只能从(i,m) 格子 ...

  6. 【bzoj1565】[NOI2009]植物大战僵尸 拓扑排序+最大权闭合图

    原文地址:http://www.cnblogs.com/GXZlegend/p/6808268.html 题目描述 输入 输出 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何 ...

  7. [BZOJ 3774] 最优选择 【最小割】

    题目链接:BZOJ - 3774 题目分析 此题与“文理分科”那道题目有些类似.都是使用最小割来求解,先加上可能获得的权值,在减掉必须舍弃的权值(最小割). 文理分科是规定每个人和 S 连就是选文,和 ...

  8. [BZOJ 2007] [Noi2010] 海拔 【平面图最小割(对偶图最短路)】

    题目链接:BZOJ - 2007 题目分析 首先,左上角的高度是 0 ,右下角的高度是 1.那么所有点的高度一定要在 0 与 1 之间.然而选取 [0, 1] 的任何一个实数,都可以用整数 0 或 1 ...

  9. BZOJ 2109 航空管制(拓扑排序+贪心)

    绝世好题啊.. 题意:给出一个DAG,和每个点要求出现在这个DAG里面的拓扑排序的位置<=ti,求出所有可能的拓扑排序里面每个点出现的位置的最小值. 正着做不好做,考虑反着做,建立这个图的反图. ...

随机推荐

  1. win7 远程桌面关机

    在任务管理器中, 打开运行窗口, 执行 shutdown -s 命令, 将在30秒后关闭win7, 如果需要更快, 加上 -t 10 参数 关于 shutdown 的命令行说明: C:\Users\R ...

  2. Centos5.8 安装 MySQL5.6.19

    查看已经安装的mysql: sudo yum list installed |grep mysql 删除 sudo yum remove mysql 安装 sudo rpm -ivh MySQL-se ...

  3. Android 开发之旅:view的几种布局方式及实践

    本文的主要内容就是分别介绍以上视图的七种布局显示方式效果及实现,大纲如下: 1.View布局概述 2.线性布局(Linear Layout) 2.1.Tips:android:layout_weigh ...

  4. codevs 1531 山峰

    codevs 1531 山峰 题目描述 Description Rocky山脉有n个山峰,一字排开,从西向东依次编号为1, 2, 3, --, n.每个山峰的高度都是不一样的.编号为i的山峰高度为hi ...

  5. hadoop 2.6全分布安装

    环境:centos 6.6 + hadoop2.6 虚拟机:(vmware fusion 7.0.0) 虚拟机hostname      /    IP地址 master / 192.168.187. ...

  6. spring 3.2.x + struts2 + mybatis 3.x + logback 整合配置

    与前面的一篇mybatis 3.2.7 与 spring mvc 3.x.logback整合 相比,只是web层的MVC前端框架,从spring mvc转换成struts 2.x系列,变化并不大 一. ...

  7. 20145222GDB调试汇编堆栈过程分析

    GDB调试汇编堆栈过程分析 实践代码example.c #include<stdio.h> short addend1 = 1; static int addend2 = 2; const ...

  8. Linux下SVN安装与基本操作

    1.安装svn linux下通过yum安装svn yum -y install subversion 本地Windows系统安装TortoiseSVN 2.配置 建立版本库目录 mkdir /home ...

  9. 【监控】WebServer入库与缓存更新代码优化小计

    问题描述: 通过WebServer将监控数据入库到Hbase,在入库之前需要将指标与ip的列表更新到缓存中,以便前台页面随时选择查看.前两天上了一些新用户导致负载增加,逐渐发现某些用户的监控场景出现丢 ...

  10. nios II--实验5——定时器硬件部分

    定时器 硬件开发 新建原理图 打开Quartus II 11.0,新建一个工程,File -> New Project Wizard…,忽略Introduction,之间单击 Next>  ...