bzoj1565: [NOI2009]植物大战僵尸

链接

https://www.lydsy.com/JudgeOnline/problem.php?id=1565

思路

很容易的想到最大权闭合子图

但这个图是有环的

有环的地方当然是都过不去的地方

显然他所保护的地方也是过不去的

他保护的地方的保护的地方也是过不去的

等等

还有这个这一行的[1,i]也是过不去的

tarjan之后递归判一下就行了

错误

好菜欧,调试了半天

其实我一开始以为环上就有了他所保护的地方

改了之后又没想到他保护的地方的保护的地方也是不可以过去的

好菜欧

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+7,M=107,inf=0x3f3f3f3f;
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,m,S,T,Score[M][M],id[M][M];
vector<pair<int,int> > dsr[M][M];
bool mmp[M][M];
pair<int,int> kkk[M*M];
struct node {
int u,v,nxt,cap;
}e[N];
int head[N],tot=1;
void add_edge(int u,int v,int cap) {
e[++tot].u=u;
e[tot].v=v;
e[tot].cap=cap;
e[tot].nxt=head[u];
head[u]=tot;
}
void add(int u,int v,int cap) {
add_edge(u,v,cap);
add_edge(v,u,0);
}
int dis[N];
queue<int> q;
bool bfs() {
memset(dis,-1,sizeof(dis));
q.push(S);
dis[S]=0;
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(dis[v]==-1&&e[i].cap) {
dis[v]=dis[u]+1;
q.push(v);
}
}
}
return dis[T]!=-1;
}
int dfs(int u,int f) {
if(u==T) return f;
int rest=f;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(dis[v]==dis[u]+1&&e[i].cap&&rest) {
int t=dfs(v,min(e[i].cap,rest));
if(!t) dis[v]=0;
e[i].cap-=t;
e[i^1].cap+=t;
rest-=t;
}
}
return f-rest;
}
int dinic() {
int ans=0;
while(bfs())
ans+=dfs(S,inf);
return ans;
}
int dfn[N],low[N],stak[N],top,cnt,vis[N],belong[N];
vector<int> BE[N];
void tarjan(int u) {
dfn[u]=low[u]=++cnt;
vis[u]=1;
stak[++top]=u;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(!e[i].cap) continue;
if(!dfn[v]) {
tarjan(v);
low[u]=min(low[u],low[v]);
} else if(vis[v]) {
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]) {
belong[0]++;
while(stak[top]!=u) {
vis[stak[top]]=0;
belong[stak[top]]=belong[0];
BE[belong[0]].push_back(stak[top]);
top--;
} top--;
vis[u]=0;
BE[belong[0]].push_back(u);
belong[u]=belong[0];
}
}
void AC(int u) {
if(mmp[kkk[u].first][kkk[u].second]) return;
for(int k=1;k<=kkk[u].second;++k) mmp[kkk[u].first][k]=1;
mmp[kkk[u].first][kkk[u].second]=1;
for(vector<pair<int,int> >::iterator it=dsr[kkk[u].first][kkk[u].second].begin();it!=dsr[kkk[u].first][kkk[u].second].end();++it)
// for(auto it : dsr[kkk[u].first][kkk[u].second])
AC(id[it->first][it->second]);
}
int main() {
n=read(),m=read();
for(int i=1,js=0;i<=n;++i) { for(int j=1;j<=m;++j) {
id[i][j]=++js;
kkk[js]=make_pair(i,j);
}}
for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) {
Score[i][j]=read();
int gs=read();
for(int k=1;k<=gs;++k) {
int x=read()+1,y=read()+1;
dsr[i][j].push_back(make_pair(x,y));
}
if(j>1)
dsr[i][j].push_back(make_pair(i,j-1));
}}
S=n*m+1,T=n*m+2;
for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) {
for(vector<pair<int,int> >::iterator it=dsr[i][j].begin();it!=dsr[i][j].end();++it) {
add(id[i][j],id[it->first][it->second],inf);
}
}}
for(int i=1;i<=n*m;++i)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=tot;i++) {
if(belong[e[i].u]==belong[e[i].v]) {
AC(e[i].u);
}
}
memset(head,0,sizeof(head));
memset(e,0,sizeof(e));
tot=1;
for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) {
if(mmp[i][j]==1) continue;
if(j!=m&&mmp[i][j+1]!=1) add(id[i][j],id[i][j+1],inf);
// for(auto it : dsr[i][j]) {
for(vector<pair<int,int> >::iterator it=dsr[i][j].begin();it!=dsr[i][j].end();++it) {
if(mmp[it->first][it->second]!=1)
add(id[it->first][it->second],id[i][j],inf);
}
}}
int sum=0;
for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) {
if(Score[i][j]>0&&!mmp[i][j]) sum+=Score[i][j];
if(mmp[i][j]==1) continue;
if(Score[i][j]>0) add(S,id[i][j],Score[i][j]);
else add(id[i][j],T,-Score[i][j]);
}}
int ans=sum-dinic();
printf("%d\n",ans);
return 0;
}

bzoj1565: [NOI2009]植物大战僵尸 最大权闭合子图,tarjan的更多相关文章

  1. BZOJ1565[NOI2009]植物大战僵尸——最大权闭合子图+拓扑排序

    题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plants防守,而Zombies进攻.该款游戏包含多 ...

  2. P2805 [NOI2009]植物大战僵尸 + 最大权闭合子图 X 拓扑排序

    传送门:https://www.luogu.org/problemnew/show/P2805 题意 有一个n * m的地图,你可以操纵僵尸从地图的右边向左边走,走的一些地方是有能量值的,有些地方会被 ...

  3. BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)

    题意 自己看吧 BZOJ传送门 分析 - 这道题其实就是一些点,存在一些二元限制条件,即如果要选uuu则必须选vvv.求得到的权值最大是多少. 建一个图,如果选uuu必须选vvv,则uuu向vvv连边 ...

  4. Bzoj 1565: [NOI2009]植物大战僵尸 最大权闭合图,拓扑排序

    题目: http://cojs.tk/cogs/problem/problem.php?pid=410 410. [NOI2009] 植物大战僵尸 ★★★   输入文件:pvz.in   输出文件:p ...

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

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

  6. BZOJ1565 [NOI2009]植物大战僵尸(拓扑排序 + 最大权闭合子图)

    题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=1565 Description Input Output 仅包含一个整数,表示可以 ...

  7. BZOJ1565 [NOI2009]植物大战僵尸 【最大权闭合子图 + tarjan缩点(或拓扑)】

    题目 输入格式 输出格式 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0. 输入样例 3 2 10 0 20 0 -10 0 -5 1 0 0 100 ...

  8. [bzoj1565][NOI2009]植物大战僵尸_网络流_拓扑排序

    植物大战僵尸 bzoj1565 题目大意:给你一张网格图,上面种着一些植物.你从网格的最右侧开始进攻.每个植物可以对僵尸提供能量或者消耗僵尸的能量.每个植物可以保护一个特定网格内的植物,如果一个植物被 ...

  9. [BZOJ1565][NOI2009]植物大战僵尸-[网络流-最小割+最大点权闭合子图+拓扑排序]

    Description 传送门 Solution em本题知识点是用网络流求最大点权闭合子图. 闭合图定义:图中任何一个点u,若有边u->v,则v必定也在图中. 建图:运用最小割思想,将S向点权 ...

随机推荐

  1. List<String> 2List <Long>

    public static List<Integer> CollStringToIntegerLst(List<String> inList){ List<Integer ...

  2. caffe训练模型中断的解决办法(利用solverstate)

    caffe训练过程中会生成.caffemodel和.solverstate文件,其中caffemodel为模型训练文件,可用于参数解析,solverstate为中间状态文件 当训练过程由于断电等因素中 ...

  3. linux整理

    文件查看命令 cat [OPTION]... [FILE]...  - E: 显示行结束符$ -n: 对显示出的每一行进行编号 -A:显示所有控制符 -b:非空行编号 -s:压缩连续的空行成一行 he ...

  4. VM虚拟机配置固定IP

    linux下vmware桥接模式.静态ip上外网的配置 http://blog.csdn.net/zdh_139/article/details/73456654 虚拟机网络改成桥接模式 vi /et ...

  5. html5-新布局元素header,footer

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  6. html5-常用的通用元素

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  7. Java基础语法(二 )

    五.运算符 *算术运算符 *赋值运算符 *关系运算符 *逻辑运算符 *位运算符 *三目运算符 算术运算符 *+,-,*,/都是比较简单的操作 *+的几种作用: 加法 正数 字符串连接符 *除法的时候要 ...

  8. quick player no exit

    QuickXDev插件自动升级后player no exist 昨晚上QuickXDev插件运行还ok,今天打开电脑启动sublime text2后,右键run with player提示player ...

  9. 正确把mysql数据库从windows迁移到linux系统上的方法

    (一)用mysqldump命令导出数据库文件: 在windows下cd到Mysql的bin目录: c:/data.txt这个目录和导出的文本名可以自己随便取,-B 后面的是表名,我要导出的表明叫use ...

  10. 爬虫--cheerio

    const cheerio = require('cheerio') const $ = cheerio.load('<h2 class="title">Hello w ...