[NOI2009] 植物大战僵尸

码风略毒瘤

我怕不是疯了

正文

这题花了我3h。其实想法有了就好想,可惜,我没有想法。

其实,一开始,做这个题我想了贪心和dp的方法,但是,因为一个很神奇的植物的保护范围,所以我把最后的尝试,放在了图论上

开始时,其实我也不知道怎么建边,

because 僵尸只能一步步的进攻

  • 建一个边,从每一行的前一个向后一个建边,表示一种 protect 关系

then 植物有攻击范围

  • 建一个边,从保护人向受保护人建边,表示一种 protect 关系

注意,这里的 a -> b 表示 a 保护 b

然后,我想到了是否能用 tarjan 或者 topo 来求个环,然后这些植物就是无敌的,就不考虑了。

当然,topo 的时候是考虑入度就行了,然而在我想完 topo 之后,我束手无策了。咋办,凉拌,不可做,走人(选择 topo 的原因是码量小,而且会比 topo 快,当然事实上 topo 还有更重要的一些优点)

然后我的想法是,类似于接着做 topo,但是,发现没有最优子结构之后果断放弃。再想想是否可以树形dp(话说这是一个名词),就像 CF467D 它那题也是跑了一个 tarjan ,之后发现状态无法很好的定义,所以。。凉凉。

我几乎放弃了图论的算法,准备写一个暴力,开阔思路。

暴力思想如下:

  • 枚举放僵尸的过程
  • 终止条件是没有路能放僵尸
  • 注意:这是个回溯算法!
  • 时间复杂度是 (O(2^{nm^{m}})),哈哈

崩了,崩了!

丝毫没有起到开阔思路的操作,还增添了我对暴力的好感。。我又回归了图论

ps:注意我现在操作的是反向图即 (forall (u,v) in E) 则有 vu 的保护

我们知道,如果选了一个点,那么我一定要选出它的后继,所以,我陷入了 topo 的遐想,在之后崩了。

我点开算法标签 最大流,???黑人问号,最大闭合子图,听都没听说过。于是我 baidu 了下然后,看了一下最大闭合子图的一些文章,真是豁然开朗!

这个算法刚好能够解决我的问题,我们只需要建一个反图,然后这就满足了一个 $forall u in V' $ 且有 ((u,v) in E) 则必有 (v in E)的性质(这就是为啥叫闭合了)

献上代码

/* make by ltao */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <set>
#include <list>
#include <map>
#include <time.h>
#include <fstream>
typedef unsigned long long ull;
typedef double db;
typedef long long ll;
#define fake int
#define sz 666666
#define inf sz
#define get() getchar()
using namespace std;
string read_str(){
	string x;
	char ch=get();
	while(ch=='
'||ch=='
'||ch==' ') ch=get();
	while(ch!='
'&&ch=='
'&&ch!=' ')x+=ch,ch=get();
	return x;
}
char read_ch(){
	char ch=get();
	while(ch=='
'||ch=='
'||ch==' ') ch=get();
	return ch;
}
int read(){
	int x=0;bool f=0;
	char ch=get();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=1;
		ch=get();
	}
	while(ch<='9'&&ch>='0'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=get(); 
	}
	return f?-x:x;
}
const int Maxm=2*1e5+11,Maxn=2002;
int n,m,s,t,h[Maxn],cnt,maxflow,sco[Maxn],w,x,y,in[Maxn],sum,dep[Maxn],cur[Maxn];
bool can[Maxn];
struct Edge{
	int fr,to,lac,flow;
	void insert(int x,int y,int z){
		fr=x;to=y;
		lac=h[x];
		h[x]=cnt++;
		flow=z;
	}
}edge[Maxm],vedge[Maxm];

bool bfs(int s,int t){
	memset(dep,-1,sizeof dep);
	memcpy(cur,h,sizeof cur);
	queue<int> q;
	q.push(s);dep[s]=0;
	while(!q.empty()){
		int fr=q.front();
		q.pop();
		for(int i=h[fr];i!=-1;i=edge[i].lac){
			int to=edge[i].to;
			if(!edge[i].flow||dep[to]!=-1) continue;
			dep[to]=dep[fr]+1;
			q.push(to);
			if(to==t){
				while(!q.empty()) q.pop();
				return 1;
			}
		} 
	}
	return 0;
}
int dfs(int u,int min1){
	if(u==t) return min1;
	int sum=min1;
	for(int i=cur[u];i!=-1;i=edge[i].lac){
		int to=edge[i].to;
		if(!edge[i].flow||dep[to]!=dep[u]+1) continue;
		int ret=dfs(to,min(sum,edge[i].flow));
		cur[u]=i;
		edge[i].flow-=ret,edge[i^1].flow+=ret,sum-=ret;
		if(sum==0) break;
	}
	return min1-sum;
}
void Dinic(int s,int t){
	while(bfs(s,t)) 
		maxflow+=dfs(s,0x3f3f3f3f);
}
int main() {
	n=read();m=read();s=0;t=n*m+1;
	memset(h,-1,sizeof h);
	for(int i=1;i<=n*m;i++){
		sco[i]=read();
		w=read();
		while(w--){
			x=read();y=read();
			edge[cnt].insert(i,x*m+y+1,0);
			in[x*m+y+1]++;
		}
		//做他保护的 
		if(i%m!=1){
			edge[cnt].insert(i,i-1,0);
			in[i-1]++;
		}
		//连接之前的 
	}
	//topo
	queue <int> q;
	for(int i=m;i<=n*m;i+=m)
		if(in[i]==0){
			q.push(i);
		}
	while(!q.empty()){
		int fr=q.front();q.pop();
		can[fr]=1;
		for(int i=h[fr];i!=-1;i=edge[i].lac){
			int to=edge[i].to;
			in[to]--;
			if(!in[to]) q.push(to);
		}
	}
	//做topo
	int vcnt=cnt;cnt=0;
	memset(h,-1,sizeof h);
	memcpy(vedge,edge,sizeof vedge); 
	for(int i=0;i<vcnt;i++){
		int to=vedge[i].to,fr=vedge[i].fr;
		if(can[fr]&&can[to]){
			//由于最大权闭合子图 
			//我们 to 收到 fr 的保护
			//所以有 to 必有 fr
			edge[cnt].insert(to,fr,inf);
			edge[cnt].insert(fr,to,0);
		}
	}
	//连接汇点和源点 
	for(int i=1;i<=n*m;i++)
		if(can[i]){
			if(sco[i]>0){
				edge[cnt].insert(s,i,sco[i]);
				edge[cnt].insert(i,s,0);
				sum+=sco[i];
			}
			if(sco[i]<0){
				edge[cnt].insert(i,t,-sco[i]);
				edge[cnt].insert(t,i,0);
			}
		}
	Dinic(s,t);
	printf("%d",sum-maxflow);
	return 0;
}

主要的思想是 topo+Dinic 就好了

其实,自己意会一下就可以知道那个算法的正确性

是的,我就是疯了

我怎么会跟qs聊天。。

跟她一起,我真是越来越不正常了

原文地址:https://www.cnblogs.com/zhltao/p/12337345.html