BZOJ 1565 NOI2009 植物大战僵尸 topo+最小割(最大权闭合子图)
题目链接:https://www.luogu.org/problemnew/show/P2805(bzoj那个实在是有点小小的辣眼睛。。。我就把洛谷的丢出来吧。。。)
题意概述:给出一张有向图,这张有向图上的每个点都有一个点权,想要访问某个点必须要先访问这个点所能够访问(遍历)到的所有点,在访问到一个点之后将会得到这个点的权值(可正可负)。问访问这张图可以得到的最大点权和。
原题说过来说过去实际上是描述了一个植物之间的保护关系,也就是说明了植物之间的先后访问顺序之间的关系。可以描述为要“要访问点a,先要访问点b”这样的形式,并且题意总结出来之后很容易发现这就是一个最大权闭合子图问题。
但是我们注意到原题给出的并不一定是一个DAG图。事实上,可能有些植物互相保护,导致僵尸只能当炮灰。。。。于是我们需要把环去掉,这一步可以topo序解决,只是不是真的topo,而是从入度为0的点开始的(访问所有可以不经过环就可以访问到的点)。
然后就是直接网络流上跑最大权闭合子图。但是值得注意的是最大权闭合子图是满足一种推导关系,即上面的“要访问点a,先要访问先b”这种关系形成的一条有向边,容量为inf,因为要满足这样的推导关系,所以上面求topo的时候连的边要反过来。然后原点向所有点权为正的边连一条边,容量为点权;所有点权为负的点向汇点连一条边,容量为点权的相反数。在求最小割的时候如果一条边被割掉,那么意义就是做出选择(S有关的边是不选这个点,T有关的边是选了这个点)之后付出的代价。
最后只需要把所有的正权点权值相加(可以得到的最大收益),减去最小割(付出的最小代价),就是我们最终获得的最大收益。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
const int MAXN=;
const int MAXM=; int N,M,sco[MAXN][MAXM];
struct XY{ int x,y; };
vector<XY>att[MAXN][MAXM];
struct graph{
static const int maxn=;
static const int maxm=;
struct edge{ int from,to,next; }E[maxm];
int n,first[maxn],np,rd[maxn],topo[maxn];
graph(){ np=; }
void add_edge(int u,int v){
E[++np]=(edge){u,v,first[u]};
first[u]=np;
}
void topo_sort(){
queue<int>q;
for(int i=;i<=n;i++)
if(!rd[i]) topo[i]=,q.push(i);
while(!q.empty()){
int i=q.front(); q.pop();
for(int p=first[i];p;p=E[p].next){
int j=E[p].to;
if(--rd[j]==) topo[j]=,q.push(j);
}
}
}
}gp;
struct NET{
static const int maxn=;
static const int maxm=;
static const int inf=1e7+;
struct edge{ int from,to,next,cap,flow; }E[maxm<<];
int S,T,n,first[maxn],np,fl[maxn],gap[maxn],d[maxn],cur[maxn];
NET(){ np=; }
void add_edge(int u,int v,int w){
E[++np]=(edge){u,v,first[u],w,};
first[u]=np;
E[++np]=(edge){v,u,first[v],,};
first[v]=np;
}
void BFS(){
queue<int>q;
for(int i=;i<=n;i++) d[i]=n;
d[T]=; q.push(T);
while(!q.empty()){
int i=q.front(); q.pop();
for(int p=first[i];p;p=E[p].next){
int j=E[p].to,pp=(p-^)+;
if(E[pp].cap>E[pp].flow&&d[j]==n) d[j]=d[i]+,q.push(j);
}
}
}
int augment(){
int now=T,flow=inf;
while(now!=S){
flow=min(flow,E[fl[now]].cap-E[fl[now]].flow);
now=E[fl[now]].from;
}
now=T;
while(now!=S){
E[fl[now]].flow+=flow,E[(fl[now]-^)+].flow-=flow;
now=E[fl[now]].from;
}
return flow;
}
int ISAP(){
memcpy(cur,first,sizeof(first));
BFS();
for(int i=;i<=n;i++) gap[d[i]]++;
int now=S,flow=;
while(d[S]<n){
if(now==T) flow+=augment(),now=S;
bool ok=;
for(int p=cur[now];p;p=E[p].next){
int j=E[p].to;
if(E[p].cap>E[p].flow&&d[j]+==d[now]){
ok=,fl[j]=cur[now]=p,now=j;
break;
}
}
if(!ok){
int minl=n;
for(int p=first[now];p;p=E[p].next){
int j=E[p].to;
if(E[p].cap>E[p].flow&&d[j]+<minl) minl=d[j]+;
}
if(--gap[d[now]]==) break;
gap[d[now]=minl]++;
cur[now]=first[now];
if(now!=S) now=E[fl[now]].from;
}
}
return flow;
}
}net; void data_in()
{
scanf("%d%d",&N,&M);
int w,x,y;
for(int i=;i<=N;i++)
for(int j=;j<=M;j++){
scanf("%d%d",&sco[i][j],&w);
for(int k=;k<=w;k++){
scanf("%d%d",&x,&y);
att[i][j].push_back((XY){x+,y+});
}
}
}
int idx(int x,int y){ return (x-)*M+y; }
void build_net()
{
for(int i=;i<=N;i++)
for(int j=;j<=M;j++){
int id=idx(i,j);
for(int k=;k+j<=M;k++){
gp.add_edge(id+k,id);
gp.rd[id]++;
}
for(int k=;k<att[i][j].size();k++){
int _id=idx(att[i][j][k].x,att[i][j][k].y);
gp.add_edge(id,_id); gp.rd[_id]++;
}
}
gp.n=N*M; gp.topo_sort();
for(int p=;p<=gp.np;p++){
int x=gp.E[p].from,y=gp.E[p].to;
if(gp.topo[x]&&gp.topo[y]) net.add_edge(y,x,net.inf);
}
net.n=N*M+,net.S=net.n-,net.T=net.n;
for(int i=;i<=N;i++)
for(int j=;j<=M;j++) if(gp.topo[idx(i,j)]){
if(sco[i][j]>) net.add_edge(net.S,idx(i,j),sco[i][j]);
else if(sco[i][j]<) net.add_edge(idx(i,j),net.T,-sco[i][j]);
}
}
void work()
{
build_net();
int sum=;
for(int i=;i<=N;i++)
for(int j=;j<=M;j++)
if(sco[i][j]>&&gp.topo[idx(i,j)]) sum+=sco[i][j];
printf("%d\n",sum-net.ISAP());
}
int main()
{
data_in();
work();
return ;
}
BZOJ 1565 NOI2009 植物大战僵尸 topo+最小割(最大权闭合子图)的更多相关文章
- [BZOJ1565][NOI2009]植物大战僵尸-[网络流-最小割+最大点权闭合子图+拓扑排序]
		Description 传送门 Solution em本题知识点是用网络流求最大点权闭合子图. 闭合图定义:图中任何一个点u,若有边u->v,则v必定也在图中. 建图:运用最小割思想,将S向点权 ... 
- b2OJ_1565_[NOI2009]植物大战僵尸_拓扑排序+最大权闭合子图
		b2OJ_1565_[NOI2009]植物大战僵尸_拓扑排序+最大权闭合子 题意:n*m个植物,每个植物有分数(可正可负),和能保护植物的位置.只能从右往左吃,并且不能吃正被保护着的,可以一个不吃,求 ... 
- BZOJ1565 [NOI2009]植物大战僵尸(拓扑排序 + 最大权闭合子图)
		题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=1565 Description Input Output 仅包含一个整数,表示可以 ... 
- bzoj 1565 [NOI2009]植物大战僵尸 解题报告
		1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2161 Solved: 1000[Submit][Stat ... 
- BZOJ 1565: [NOI2009]植物大战僵尸( 最小割 )
		先拓扑排序搞出合法的, 然后就是最大权闭合图模型了.... --------------------------------------------------------------------- ... 
- Bzoj 1565: [NOI2009]植物大战僵尸  最大权闭合图,拓扑排序
		题目: http://cojs.tk/cogs/problem/problem.php?pid=410 410. [NOI2009] 植物大战僵尸 ★★★ 输入文件:pvz.in 输出文件:p ... 
- BZOJ 1565 [NOI2009]植物大战僵尸 | 网络流
		传送门 BZOJ 1565 题解 这道题也是个经典的最大权闭合子图-- 复习一下最大权闭合子图是什么? 就是一个DAG上,每个点有个或正或负的点权,有的点依赖于另外一些点(如果选这个点,则被依赖点必选 ... 
- bzoj 1565  [NOI2009]植物大战僵尸【tarjan+最大权闭合子图】
		一上来以为是裸的最大权闭合子图,上来就dinic -然后没过样例.不得不说样例还是非常良心的给了一个强连通分量,要不然就WA的生活不能自理了 然后注意到有一种特殊情况:每个植物向他保护的植物连边(包括 ... 
- BZOJ 1565: [NOI2009]植物大战僵尸(网络流+缩点)
		传送门 解题思路 最大权闭合子图.但是要注意一些细节,假如有一堆植物形成一个环,那么这些植物都是无敌的,并且他们保护的植物是无敌的,他们保护的保护的植物是无敌 的.所以要缩点,然后拓扑排序一次判无敌, ... 
随机推荐
- [Linux/Unix]用户和用户组管理
			Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统的用户,都必须拥有自己的账号. 实现用户的管理,主要做: 用户账号的添加.删除.修改: 用户口令的管理: 用户组的管理. (一)用户的 ... 
- Linux查看日志命令- more、less、tail、head命令的区别
			参考:https://blog.csdn.net/caib1109/article/details/52195942 1.more 2.tail 3.less 4.cat 5.head 
- orcal 数据库 maven架构 ssh框架 的全注解环境模版 maven中央仓库批量删除lastupdated文件后依然是lastupdated解决方法 mirror aliyun中央仓库
			批量删除文件,得用批处理文件,文件名随便,路径改成你的Repository,代码如下 rem 这里写你的仓库路径 set REPOSITORY_PATH=d:\repo rem 正在搜索... for ... 
- 网页后缀html、htm、shtml、shtm有什么区别?
			每一个网页或者说是web页都有其固定的后缀名,不同的后缀名对应着不同的文件格式和不同的规则.协议.用法,最常见的web页的后缀名是.html和.htm,但这只是web页最基本的两种文件格式,今天我们来 ... 
- python的元组数据类型及常用操作
			Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可. 如下实例: tup1 = ('physi ... 
- 【mysql学习-2】
			part-1: USE mysql;CREATE TABLE tb_x(id INT,NAME CHAR(10));INSERT INTO tb_x VALUES(5,"a");S ... 
- Python特别low的一个文字游戏
			闲来无事 ,调侃舍友的游戏 import os class Role(): def __init__(self,name,sex,fighting): self.name=name self.sex= ... 
- 使用mysql5.7版本数据库需要注意的地方/持续更新
			数据库mysql 5.7版本的初始密码修改 安装完后实在是找不到初始密码的文件,后面发现再错误日志中 先关闭mysql pkill mysqld 安全模式启动数据库并修改密码 mysqld_safe ... 
- PublicCMS 网站漏洞 任意文件写入并可提权服务器权限
			PublicCMS是目前网站系统中第一个采用JAVA架构 TOMCAT+Apcche+Mysql数据库架构的CMS网站,开源,数据承载量大,可以承载到上千万的数据量,以及用户的网站并发可达到上千万的P ... 
- python2.7入门---模块(Module)
			来,这次我们就看下Python 模块(Module).它是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句.模块让你能够有逻辑地组织你的 Pytho ... 
