洛谷2805 [NOI2009]植物大战僵尸 (拓扑排序+最小割)
坚决抵制长题面的题目!
首先观察到这个题目中,我们会发现,我们对于原图中的保护关系(一个点右边的点对于这个点也算是保护)
相当于一种依赖。
那么不难看出这个题实际上是一个最大权闭合子图模型。
我们直接对于权值为负数的边,\(S\rightarrow now\),流量是\(-a[i][j]\),表示打掉他要花这么多的代价。
对于权值为正的边,\(now \rightarrow T\) ,流量是\(a[i][j]\),表示如果割掉这个边,表示放弃他的收益。
(这里之所以\(S和T\)不能反过来,因为我们跑最小割的时候,是要保证S到T不连通,所以你要让负的权值与S相连,才会让依赖关系有意义)
对于每个点,向他保护的点连边,边权为\(inf\)。表示这个关系不能打破。
同时一个点右边的点,向这个点连边,流量也是\(inf\),因为右边的点要比左边的点先被打。
最后的答案就是\(正权值的sum - 最小割\)(总的收益,减去花费和舍去的。)
那么建出来图,我们会发现其实这个是有问题的。
因为可能存在环的情况。
(\(A保护B,B保护A\))
那么应该怎么办呢?
我们发现如果存在一个环,那么环能保护到的点,以及再往后的点,都是无敌的!
所以合法的点,就是从起点开始,找到所有的满足起点到这个点的所有路径都不经过环的 点。
那么这个可以通过拓扑排序来实现。
qwq
只需要一开始先把所有的依赖关系,跑一遍拓扑排序。
然后选出来有效的点,再建图就ok
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk make_pair
#define ll long long
#define pb push_back
using namespace std;
inline int read()
{
  int x=0,f=1;char ch=getchar();
  while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
  while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}
const int maxn = 3010;
const int maxm = 2e6+1e2;
const int inf = 1e9;
int n,m,cnt=1;
int point[maxn],nxt[maxm],to[maxm],val[maxm];
int h[maxn],in[maxn];
int s,t;
int a[maxn][maxn];
int sum;
int num;
int dfn[maxn];
int tag[maxn];
vector<int> v[maxn];
void init()
{
	cnt=1;
	memset(point,0,sizeof(point));
	memset(in,0,sizeof(in));
}
void add(int x,int y)
{
	nxt[++cnt]=point[x];
	to[cnt]=y;
	point[x]=cnt;
	in[y]++;
}
void addedge(int x,int y,int w)
{
	nxt[++cnt]=point[x];
	to[cnt]=y;
	val[cnt]=w;
	point[x]=cnt;
}
void insert(int x,int y,int w)
{
	addedge(x,y,w);
	addedge(y,x,0);
}
queue<int> q;
bool bfs(int s)
{
	memset(h,-1,sizeof(h));
	h[s]=0;
	q.push(s);
	while (!q.empty())
	{
		int x = q.front();
		q.pop();
		for (int i=point[x];i;i=nxt[i])
		{
			int p=to[i];
			if (h[p]==-1 && val[i]>0)
			{
				h[p]=h[x]+1;
				q.push(p);
			}
		}
	}
	if (h[t]==-1) return false;
	return true;
}
int dfs(int x,int low)
{
    if (x==t || low==0) return low;
    int totflow=0;
    for (int i=point[x];i;i=nxt[i])
    {
    	int p = to[i];
    	if (h[p]==h[x]+1 && val[i]>0)
    	{
    		int tmp = dfs(p,min(low,val[i]));
    		val[i]-=tmp;
    		val[i^1]+=tmp;
    		low-=tmp;
    		totflow+=tmp;
    		if (low==0) return totflow;
		}
	}
	if (low>0) h[x]=-1;
	return totflow;
}
int dinic()
{
	int ans=0;
	while (bfs(s))
	{
		ans=ans+dfs(s,inf);
	}
	return ans;
}
int getnum(int x,int y)
{
	return (x-1)*m+y;
}
void tpsort()
{
	while (!q.empty()) q.pop();
	for (int i=1;i<=num;i++)
	{
		if (!in[i]) q.push(i),tag[i]=1,dfn[i]=1;
	}
	while (!q.empty())
	{
		int x = q.front();
		q.pop();
		for (int i=point[x];i;i=nxt[i])
		{
			int p=to[i];
			in[p]--;
			if (!in[p])
			{
				dfn[p]=dfn[x]+1;
				q.push(p);
				tag[p]=1;
			}
		}
	}
}
int main()
{
  n=read(),m=read();
  num=n*m;
  for (int i=1;i<=n;i++)
    for (int j=1;j<=m;j++)
    {
    	a[i][j]=read();
        int num = read();
        for (int k=1;k<=num;k++)
        {
        	int x=read(),y=read();
        	x++,y++;
        	v[getnum(i,j)].pb(getnum(x,y));
        	add(getnum(i,j),getnum(x,y));
		}
	    if (j!=m) add(getnum(i,j+1),getnum(i,j));
	}
  tpsort();
  init();
  s=maxn-10;
  t=s+1;
  for (int i=1;i<=n;i++)
    for (int j=1;j<=m;j++)
    {
    	int now=getnum(i,j);
    	if(!tag[now]) continue;
    	if(a[i][j]>0) sum+=a[i][j];
    	for (int k=0;k<v[now].size();k++)
    	  if (tag[v[now][k]]) insert(now,v[now][k],inf);
    	if (a[i][j]>0) insert(now,t,a[i][j]);
    	else insert(s,now,-a[i][j]);
	}
  for (int i=1;i<=n;i++)
  {
  	 for (int j=1;j<=m;j++)
  	 {
  	 	int now = getnum(i,j);
  	 	int ri  = getnum(i,j+1);
  	 	if (j==m) continue;
  	 	if (!tag[now] || !tag[ri]) continue;
  	 	if (dfn[ri]>dfn[now]) swap(now,ri);
  	 	insert(ri,now,inf);
	 }
  }
  cout<<sum-dinic();
  return 0;
}
												
											洛谷2805 [NOI2009]植物大战僵尸 (拓扑排序+最小割)的更多相关文章
- P2805 [NOI2009]植物大战僵尸 (拓扑排序 + 最小割)
		
题意:N*M的矩阵 每个点上都有一颗植物 僵尸只能从每一行的最右边向左进攻 每个植物有攻击范围 可以保护在攻击范围内的植物 同时每一颗植物也保护他左边的植物 摧毁每个植物能获得价值 如果这个植物被保护 ...
 - 【BZOJ-1565】植物大战僵尸      拓扑排序 + 最小割
		
1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1972 Solved: 917[Submit][Statu ...
 - 洛谷 P2805 [NOI2009]植物大战僵尸 解题报告
		
P2805 [NOI2009] 植物大战僵尸 题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plan ...
 - 洛谷$P2805\ [NOI2009]$植物大战僵尸 网络流
		
正解:网络流 解题报告: 传送门$QwQ$ 题面好长昂,,,我大概概括下$QwQ$?有个$n\cdot m$的网格,每个格子有一株植物,击溃一株植物$(x,y)$需要付出$S_{(x,y)}$的代价( ...
 - 【bzoj1565】[NOI2009]植物大战僵尸  拓扑排序+最大权闭合图
		
原文地址:http://www.cnblogs.com/GXZlegend/p/6808268.html 题目描述 输入 输出 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何 ...
 - 2018.11.02 洛谷P2661 信息传递(拓扑排序+搜索)
		
传送门 按照题意模拟就行了. 先拓扑排序去掉不在环上面的点. 剩下的都是简单环了. 于是都dfsdfsdfs一遍求出最短的环就行. 代码: #include<bits/stdc++.h> ...
 - 洛谷P3243 [HNOI2015]菜肴制作 拓扑排序+贪心
		
正解:拓扑排序 解题报告: 传送门! 首先看到它这个约束就应该要想到拓扑排序辣QwQ 首先想到的应该是用优先队列代替队列,按照节点编号排序 然后也很容易被hack:<5,1> 正解应为5, ...
 - 【洛谷P4934】 礼物,拓扑排序
		
题目大意:给你$n$个不重复的数,其值域为$[0,2^k)$,问你至少需要将这$n$个数拆成多少个集合,使得它们互相不是对方的子集,并输出方案. 数据范围:$n≤10^6$,$k≤20$. $MD$我 ...
 - BZOJ 1565 植物大战僵尸(拓扑排序+最大权闭合子图)
		
图中的保护关系就类似于最大权闭合子图.即你想杀x,你就一定要杀掉保护x的点,那么把x向保护它的点连边.那么题目就转化成了最大权闭合子图的问题. 但是这个图有点特殊啊... 考虑有环的情况,显然这个环以 ...
 
随机推荐
- rabbitMq队列长度限制
			
x-max-length:队列最大容纳消息条数 大于设置条数的时候会把,消息队列头部(先进入消息)的消息移除 x-max-length-bytes:队列最大容量消息内存容量服务端限流内存控制流量:40 ...
 - (六)羽夏看C语言——函数
			
写在前面 由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...
 - markdown的骚气操作(一)
			
markdown 系列其他内容 markdown的骚气操作(一)✓ latex的骚气操作(二) 本文目标 主要介绍markdown锚点.索引脚注.对勾及选择框.表格显示位置和符号显示位置.绘制 ...
 - IKE~多预共享密钥问题~解决方案
			
原文链接:Configuring more than one Main-Mode Pre-Shared Key (PSK) *dialup* IPSec phase1 可能需要梯子来翻过高墙.文章内容 ...
 - sync 修饰符在Vue中如何使用
			
在有些情况下,我们可能需要对一个 prop 进行"双向绑定".不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源. 这 ...
 - 【OI】蛇形填数题的深入探究
			
题目:在 n×n 方阵里填入 1,2,...n×n, 要求蛇形填数.例如,n=4 时方阵为: 10 11 12 1 9 16 13 2 8 15 14 3 7 6 ...
 - Java中的三大特性:封装、继承、多态
			
封装: 概念:封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问,适当的封装可以让代码更容易理解与维护,也加强了代码的安全性. 原则:将属性隐藏起来,若需要访问某个属性,提供公共方法对 ...
 - Elasticsearch2.4.6版本  在linux  命令行 对数据的增删改操作
			
一._cluster系列:查询设置集群状态 1.设置集群状态 curl -XGET 10.68.120.167:9204/_cluster/health?pretty=true pretty=true ...
 - LateX出坑
			
1 公式是用$ 包围着的 $ 2 \begin{equation} 里面的公式自动编号 \end{equation} 要达成这样的效果,暂时想到如下方法: 1 \begin{equation} ...
 - FormData上传文件  带进度条
			
* jQuery ajax FormData 上传文件 template $.ajax({ url: url, type: 'POST', data: new FormData(form), dat ...