传送门

解题思路

  最大权闭合子图。但是要注意一些细节,假如有一堆植物形成一个环,那么这些植物都是无敌的,并且他们保护的植物是无敌的,他们保护的保护的植物是无敌 的。所以要缩点,然后拓扑排序一次判无敌,然后剩下的就是一个最大权闭合子图模板了。源点向正权点连流量为正权的边,负权点向汇点连流量为负权绝对值的边,然后保护关系之间连流量为正无穷的边。最后答案为总正权-最小割。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue> using namespace std;
const int MAXN = 605;
const int MAXM = MAXN*MAXN;
const int inf = 0x3f3f3f3f; inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
} int n,m,w[MAXN],head[MAXN],cnt,to[MAXM<<1],nxt[MAXM<<1],val[MAXM<<1];
int S,T,d[MAXN],dfn[MAXN],low[MAXN],col[MAXN],stk[MAXN],top,siz[MAXN];
int tot,col_num,du[MAXN],wt[MAXN],num,cur[MAXN],ans;
bool vis[MAXN],del[MAXN];
queue<int> Q; struct Edge{
int u,v;
}edge[MAXM<<1]; inline void add(int bg,int ed){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
} inline void addedge(int bg,int ed,int w){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt,val[cnt]=w;
} bool bfs(){
while(Q.size()) Q.pop();
memset(d,0,sizeof(d));d[S]=1;Q.push(S);
while(Q.size()){
int x=Q.front();Q.pop();
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(!d[u] && val[i]){
d[u]=d[x]+1;
if(u==T) return true;
Q.push(u);
}
}
}
return false;
} int dinic(int x,int flow){
if(x==T) return flow;
int res=flow,k;
for(int &i=cur[x];i && res;i=nxt[i]){
int u=to[i];
if(d[u]==d[x]+1 && val[i]){
k=dinic(u,min(res,val[i]));
if(!k) d[u]=0;
val[i]-=k;val[i^1]+=k;res-=k;
}
}
return flow-res;
} void tarjan(int x){
dfn[x]=low[x]=++tot;vis[x]=1;stk[++top]=x;
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(!dfn[u]) tarjan(u),low[x]=min(low[x],low[u]);
else if(vis[u]) low[x]=min(low[x],dfn[u]);
}
if(low[x]==dfn[x]){
vis[x]=0;col[x]=++col_num;wt[col_num]=w[x];
while(stk[top]!=x){
vis[stk[top]]=0;
col[stk[top--]]=col_num;
}top--;
}
} inline void topsort(){
for(int i=1;i<=col_num;i++) if(!du[i]) Q.push(i);
while(Q.size()){
int x=Q.front();Q.pop();
for(int i=head[x];i;i=nxt[i]){
int u=to[i];du[u]--;
if(del[x]) del[u]=1;
if(!du[u]) Q.push(u);
}
}
} inline void rebuild(){
memset(head,0,sizeof(head));cnt=1;
for(int i=1;i<=num;i++){
if(del[edge[i].v] || del[edge[i].u]) continue;
addedge(edge[i].v,edge[i].u,inf),addedge(edge[i].u,edge[i].v,0);
}
for(int i=1;i<=col_num;i++)
if(!del[i]){
if(wt[i]>0) addedge(S,i,wt[i]),addedge(i,S,0),ans+=wt[i];
else addedge(i,T,-wt[i]),addedge(T,i,0);
}
} inline void solve(){
while(bfs()) {memcpy(cur,head,sizeof(head));ans-=dinic(S,inf);}
printf("%d\n",ans);
} int main(){
n=rd(),m=rd();S=n*m+1;T=n*m+2;int x,y;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
w[(i-1)*m+j]=rd();num=rd();
while(num--){
x=rd()+1,y=rd()+1;
add((i-1)*m+j,(x-1)*m+y);
}
if(j!=1) add((i-1)*m+j,(i-1)*m+j-1);
}
for(int i=1;i<=n*m;i++) if(!dfn[i]) tarjan(i);num=0;
for(int i=1;i<=n*m;i++)
for(int j=head[i];j;j=nxt[j]){
if(col[i]==col[to[j]]) del[col[i]]=1;
else edge[++num].u=col[i],edge[num].v=col[to[j]];
}
memset(head,0,sizeof(head));cnt=0;
for(int i=1;i<=num;i++) {
du[edge[i].v]++;
add(edge[i].u,edge[i].v);
}
topsort();rebuild();solve();
return 0;
}

BZOJ 1565: [NOI2009]植物大战僵尸(网络流+缩点)的更多相关文章

  1. BZOJ 1565 [NOI2009]植物大战僵尸 | 网络流

    传送门 BZOJ 1565 题解 这道题也是个经典的最大权闭合子图-- 复习一下最大权闭合子图是什么? 就是一个DAG上,每个点有个或正或负的点权,有的点依赖于另外一些点(如果选这个点,则被依赖点必选 ...

  2. bzoj 1565 [NOI2009]植物大战僵尸 解题报告

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

  3. BZOJ 1565: [NOI2009]植物大战僵尸( 最小割 )

    先拓扑排序搞出合法的, 然后就是最大权闭合图模型了.... --------------------------------------------------------------------- ...

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

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

  5. BZOJ 1565 NOI2009 植物大战僵尸 topo+最小割(最大权闭合子图)

    题目链接:https://www.luogu.org/problemnew/show/P2805(bzoj那个实在是有点小小的辣眼睛...我就把洛谷的丢出来吧...) 题意概述:给出一张有向图,这张有 ...

  6. bzoj 1565 [NOI2009]植物大战僵尸【tarjan+最大权闭合子图】

    一上来以为是裸的最大权闭合子图,上来就dinic -然后没过样例.不得不说样例还是非常良心的给了一个强连通分量,要不然就WA的生活不能自理了 然后注意到有一种特殊情况:每个植物向他保护的植物连边(包括 ...

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

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

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

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

  9. 洛谷$P2805\ [NOI2009]$植物大战僵尸 网络流

    正解:网络流 解题报告: 传送门$QwQ$ 题面好长昂,,,我大概概括下$QwQ$?有个$n\cdot m$的网格,每个格子有一株植物,击溃一株植物$(x,y)$需要付出$S_{(x,y)}$的代价( ...

随机推荐

  1. CSP-S2019退役记。。。

    模拟赛的时候题目就比较迷,感觉不像联赛难度的. 考完正式赛才觉得这TM算个P. Day1: 写密码的监考同学的蜜汁字体让我傻了. 0和O是一样的,9和q是一样的,1和l是一样的-- 又没有冷静下来发现 ...

  2. 四轴电池ADC监控学习

    一.硬件原理 电池供电通过两个分压电阻接地,STM32则在两电阻中间通过ADC检测电池电压.(引脚BAT_DET) 二.ADC通道初始化 //初始化电池检测ADC //开启ADC1的通道8 //Bat ...

  3. mysql学习-explain中的extra

    覆盖索引就是创建的索引和查询的字段正好个数顺序一致 using filesort:mysql使用了一个外部索引 ,而非表内索引顺序进行访问,,mysql无法利用索引完成的排序操作称为文件索引,如果你创 ...

  4. IDEA的骚操作

    1.var声明 "jack".var ==>final String name = "jack"; 2.null判空 user.null==>if( ...

  5. leetcode上的一些栈、队列问题

    20-有效的括号 思路:主要考察栈的一些基本操作,像push()(将数据压入栈顶).top()(取栈顶的数据但不删除).pop()(直接删除栈顶的元素).empty()(判断栈是否为空).这题就是先把 ...

  6. RFC6241 NETCONF

    概述 NETCONF = The Network Configuration Protocol SDN = Software Define Network NETCONF协议分为传输层.消息层.操作层 ...

  7. Linux命令 who

    who :显示当前登入系统的用户信息 显示的内容主要包括: 用户名,登录终端,上线时间,停留时间,动作,UID等 权限:所有使用者 语法: who  [option] ...[ file | arg1 ...

  8. linux性能查看调优

    一 linux服务器性能查看1.1 cpu性能查看1.查看物理cpu个数:cat /proc/cpuinfo |grep "physical id"|sort|uniq|wc -l ...

  9. 【目录】mysql 基础篇系列

    随笔分类 - mysql 基础篇系列 mysql 开发基础系列22 SQL Model(带迁移事项) 摘要: 一.概述 与其它数据库不同,mysql 可以运行不同的sql model 下, sql m ...

  10. 一句话概括 tcp三次握手

    服务端和客户端都需要直到自己均可收发,因此需要三次握手. 简化三次握手: <img width="487" alt="2018-07-10 3 42 11" ...