bzoj1565: [NOI2009]植物大战僵尸 最大权闭合子图,tarjan
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的更多相关文章
- BZOJ1565[NOI2009]植物大战僵尸——最大权闭合子图+拓扑排序
题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plants防守,而Zombies进攻.该款游戏包含多 ...
- P2805 [NOI2009]植物大战僵尸 + 最大权闭合子图 X 拓扑排序
传送门:https://www.luogu.org/problemnew/show/P2805 题意 有一个n * m的地图,你可以操纵僵尸从地图的右边向左边走,走的一些地方是有能量值的,有些地方会被 ...
- BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)
题意 自己看吧 BZOJ传送门 分析 - 这道题其实就是一些点,存在一些二元限制条件,即如果要选uuu则必须选vvv.求得到的权值最大是多少. 建一个图,如果选uuu必须选vvv,则uuu向vvv连边 ...
- Bzoj 1565: [NOI2009]植物大战僵尸 最大权闭合图,拓扑排序
题目: http://cojs.tk/cogs/problem/problem.php?pid=410 410. [NOI2009] 植物大战僵尸 ★★★ 输入文件:pvz.in 输出文件:p ...
- BZOJ 1565 植物大战僵尸 最大权闭合子图+网络流
题意: 植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性: (1)价值: (2)保护集合,也就是这个植物可以保护矩阵中的某些格子. 现在你是僵尸,你每次只能从(i,m) 格子 ...
- BZOJ1565 [NOI2009]植物大战僵尸(拓扑排序 + 最大权闭合子图)
题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=1565 Description Input Output 仅包含一个整数,表示可以 ...
- BZOJ1565 [NOI2009]植物大战僵尸 【最大权闭合子图 + tarjan缩点(或拓扑)】
题目 输入格式 输出格式 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0. 输入样例 3 2 10 0 20 0 -10 0 -5 1 0 0 100 ...
- [bzoj1565][NOI2009]植物大战僵尸_网络流_拓扑排序
植物大战僵尸 bzoj1565 题目大意:给你一张网格图,上面种着一些植物.你从网格的最右侧开始进攻.每个植物可以对僵尸提供能量或者消耗僵尸的能量.每个植物可以保护一个特定网格内的植物,如果一个植物被 ...
- [BZOJ1565][NOI2009]植物大战僵尸-[网络流-最小割+最大点权闭合子图+拓扑排序]
Description 传送门 Solution em本题知识点是用网络流求最大点权闭合子图. 闭合图定义:图中任何一个点u,若有边u->v,则v必定也在图中. 建图:运用最小割思想,将S向点权 ...
随机推荐
- install Maven
工欲善其事,必先利其器.咱们也来玩玩 Maven 这货吧!先得去下载一个. 准备工作 java开发环境(JDK) maven下载地址:http://maven.apache.org/release-n ...
- html常用文本标签(转)
内容一<br />内容二 让文本强制换行 内容一内容二 <p>段落一</p><p>段落二</p> 段落标签 段落一 段落二 <b> ...
- Django中的View视图讲解
Django中的View视图(view.py)是负责处理用户请求和返回响应的逻辑. 视图函数或视图简而言之就是一个python函数,它接受一个web请求并返回一个Web响应. 此响应可以是网页的HTM ...
- python之mysqldb模块安装
之所以会写下这篇日志,是因为安装的过程有点虐心.目前这篇文章是针对windows操作系统上的mysqldb的安装.安装python的mysqldb模块,首先当然是找一些官方的网站去下载:https:/ ...
- Java IO/NIO教程
Java IO教程 http://tutorials.jenkov.com/java-io/index.html Java NIO教程 英文版: http://tutorials.jenkov.com ...
- Codeforces Round #319 (Div. 2) D
E A tree of size n is an undirected connected graph consisting of n vertices without cycles. Conside ...
- cookie中存取中文
- Django admin模块无法调用css样式文件
在使用Django Admin开发时,发现admin模块css样式文件丢失,无法调用,使火狐浏览器提示: 此 URL 的资源不是文本: http://127.0.0.1:8000/statics/ad ...
- 特征点方法 - Harris和SURF的手工实现
整理去年做的小项目,纪念我的图像处理入门. 因为要在DSP上实现,所以完全手工C代码垒起来的,还要保证和PC端跑的结果一样,觉得可能特殊场景会有用,上传github,没有依赖任何库: 格式注释什么的暂 ...
- 变量为空代表false
name = ''#名字为空即代表False while not name:#not name=False即 真,将执行循环体 print('Enter your name:') name = inp ...