害怕地发现我以前写的Dinic几乎都是有错的……??!!!

【题目大意】

(以下摘自popoqqq大爷)给定一个m*n的草坪,每块草坪上的植物有两个属性:1.啃掉这个植物,获得收益x(可正可负)2.保护(r,c)点的植物不被啃掉。任何一个点的植物存活时,它左侧的所有植物都无法被攻击,求最大收益。

【思路】

首先我们很容易发现,植物存活有一个依赖关系,显然是一个最大权闭合图,即从被保护者指向保护者(简单来说,就是只有保护者被吃掉的情况下,被保护者才有可能被吃掉)。

注意,如果构成了一个环,则不会被吃掉;此外,当前点指向直接或间接指向一个环,也不可能被吃掉。

那么怎么删除环和指向环的节点呢?这里有一个拓扑排序常用的小技巧:

把所有边反向,从入度为0的点开始拓扑排序,能抵达的点便是保留的点。

顺便放一个拓扑排序的模板:

 1 void Topology()
2 {
3 memset(usable,0,sizeof(usable));
4 queue<int> que;
5 for (int i=S;i<=T;i++)
6 if (!into[i]) que.push(i);
7 while (!que.empty())
8 {
9 int head=que.front();que.pop();
10 usable[head]=1;
11 if (score[head]>0) ans+=score[head];
12 for (int i=0;i<rE[head].size();i++)
13 {
14 int to=rE[head][i];
15 into[to]--;
16 if (!into[to]) que.push(to);
17 }
18 }
19 }

【错误点】

一开始建图的时候正向边反向边傻傻没分清……

2016/7/29修改:突然我以前写的Dinic都是错的我要爆炸了!现在又优化了一下,更正详见注释里面。至于优化前后的效率差距:

呃……

 /*2016.7.29更正*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define S 0
#define T m*n+1
using namespace std;
const int MAXN=;
struct node
{
int to,pos,cap;
};
const int INF=0x7fffffff;
vector<int> rE[MAXN*MAXN];
vector<node> E[MAXN*MAXN];
int score[MAXN*MAXN];
int n,m,ans=;
int usable[MAXN*MAXN],into[MAXN*MAXN];
int dis[MAXN*MAXN]; void addedge(int u,int v,int w)
{
rE[v].push_back(u);
into[u]++;
E[u].push_back((node){v,E[v].size(),w});
E[v].push_back((node){u,E[u].size()-,});
} void Topology()
{
memset(usable,,sizeof(usable));
queue<int> que;
for (int i=S;i<=T;i++)
if (!into[i]) que.push(i);
while (!que.empty())
{
int head=que.front();que.pop();
usable[head]=;
if (score[head]>) ans+=score[head];
for (int i=;i<rE[head].size();i++)
{
int to=rE[head][i];
into[to]--;
if (!into[to]) que.push(to);
}
}
} bool bfs()
{
memset(dis,-,sizeof(dis));
queue<int> que;
while (!que.empty()) que.pop();
que.push(S);
dis[S]=;
while (!que.empty())
{
int head=que.front();que.pop();
if (head==T) return true; //首次抵达T即可返回,不需要整张图全部分层
for (int i=;i<E[head].size();i++)
{
node tmp=E[head][i];
if (dis[tmp.to]==- && tmp.cap && usable[tmp.to])
{
dis[tmp.to]=dis[head]+;
que.push(tmp.to);
}
}
}
return false;
} int dfs(int s,int e,int f)
{
if (s==e) return f;
int ret=;
for (int i=;i<E[s].size();i++)
{
node &tmp=E[s][i];
if (dis[tmp.to]==dis[s]+ && tmp.cap)
{
int delta=dfs(tmp.to,e,min(f,tmp.cap));
if (delta>)
{
tmp.cap-=delta;
E[tmp.to][tmp.pos].cap+=delta;
f-=delta;
ret+=delta;
if (f==) return ret;
}
else dis[tmp.to]=-;//注意一下这里要清为-1,很重要★★★★★
}
}
return ret;
} void dinic()
{
while (bfs())
{
int f=dfs(S,T,INF);
if (f) ans-=f;else break;
}
} void init()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
int w,fr=(i-)*m+j;
scanf("%d%d",&score[fr],&w);
if (score[fr]>) addedge(S,fr,score[fr]);
else if (score[fr]<) addedge(fr,T,-score[fr]);
for (int k=;k<=w;k++)
{
int r,c;
scanf("%d%d",&r,&c);
r++;c++;
int to=(r-)*m+c;
addedge(to,fr,INF);
}
if (j!=m) addedge(fr,fr+,INF);
}
} int main()
{
init();
Topology();
dinic();
printf("%d",ans);
return ;
}

【最大权闭合图】BZOJ1565-[NOI2009]植物大战僵尸的更多相关文章

  1. BZOJ1565——[NOI2009]植物大战僵尸

    1.题意:有一些点,点与点之间有保护关系,每个点都有一个权值,求能获得的最大值 2.分析:裸的最大权闭合图,用网络流进行求解,然后我们发现点与点之间的保护关系可能构成环,这样网络流是无法处理的,然后我 ...

  2. BZOJ1565: [NOI2009]植物大战僵尸

    Description Input Output 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0. Sample Input 3 2 10 0 20 0 ...

  3. 【最大权闭合子图 tarjan】bzoj1565: [NOI2009]植物大战僵尸

    dinic+tarjan板子练手题 Description Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其 中P ...

  4. P2805 [NOI2009]植物大战僵尸

    题目地址:P2805 [NOI2009]植物大战僵尸 最大权闭合子图 若有向图 \(G\) 的子图 \(V\) 满足: \(V\) 中顶点的所有出边均指向 \(V\) 内部的顶点,则称 \(V\) 是 ...

  5. 【bzoj1565】 NOI2009—植物大战僵尸

    http://www.lydsy.com/JudgeOnline/problem.php?id=1565 (题目链接) 题意 给出$n*m$的棋盘,僵尸攻击每个格子可以获得$v$的分数,每个格子又会保 ...

  6. BZOJ 1565: [NOI2009]植物大战僵尸

    1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2317  Solved: 1071[Submit][Stat ...

  7. 图论(网络流):COGS 410. [NOI2009] 植物大战僵尸

    410. [NOI2009] 植物大战僵尸 ★★★   输入文件:pvz.in   输出文件:pvz.out   简单对比时间限制:2 s   内存限制:512 MB [问题描述] Plants vs ...

  8. COGS410. [NOI2009] 植物大战僵尸

    410. [NOI2009] 植物大战僵尸 ★★★   输入文件:pvz.in   输出文件:pvz.out   简单对比时间限制:2 s   内存限制:512 MB [问题描述] Plants vs ...

  9. 【BZOJ1565】 植物大战僵尸

    Description Input Output 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0. Sample Input 3 2 10 0 20 0 ...

随机推荐

  1. el-date-picker 日期格式化 yyyy-MM-dd

    <el-date-picker format="yyyy-MM-dd" v-model="dateValue" type="date" ...

  2. nginx路由文件配置

    nginx中文文档 Nginx 的请求处理有多个阶段,比如说rewrite.access.content等等,不同的配置字段属于不同的配置阶段,不同阶段的先后执行顺序不一样,例如rewrite在con ...

  3. fork与printf缓冲问题

    printf输出条件: (1) 调用fflush: (2) 缓冲区满了: (3) 遇到\n \r这些字符 (4) 遇到scanf这些要取缓冲区的: (5) 线程或者进程退出: fork之后会拷贝父进程 ...

  4. Linux-进程间通信(N): 各种IPC的使用场景

    1. 管道:只能用于具有亲缘关系的进行通信,使用面相对较窄,实际开发中较少使用: 2. FIFO(命名管道):可以用于任意进程间的通信,对于大块数据的传输效率较高,可应用于单进程大量数据传递,和多个进 ...

  5. linux 设备树【转】

    转自:http://blog.csdn.net/chenqianleo/article/details/77779439 [-] linux 设备树 为什么要使用设备树Device Tree 设备树的 ...

  6. 【hihocoder】sam-2

    原意是把sam那一堆做完…… 这题还是很sb的,$\sum{maxlen(s)-minlen(s)+1}$就是本质不同的子串数量 然后因为suffix link的性质,maxlen[fa[s]]=mi ...

  7. 搭建selenium+python自动化环境

    1.安装python,下载地址:http://python.org---安装版本3.5.1 ps:自带setuptools和pip工具 2.然后,用pip安装开发Web App需要的第三方库:异步框架 ...

  8. MyBatis3-与Spring 4集成

    继续使用前一篇的例子http://www.cnblogs.com/EasonJim/p/7052368.html,实际项目中,通常会用Spring来管理DataSource等.充分利用Spring基于 ...

  9. python_day7学习笔记

    类 1)创建一个类 #coding=utf-8 __author__ = 'Administrator' class Employee: '所有员工的基类' empCount = 0 def __in ...

  10. gulp配合vue压缩代码格式化

    实际项目就是一个单页面.因此,我觉得用gulp足够,并且不需要webpack和vue-cli因为没有必要使用组件. 先来说一下项目结构 1. 然后来看看我的包管理package.json都用了啥,你也 ...