P2805 [NOI2009]植物大战僵尸

时间:2020-05-21
本文章向大家介绍P2805 [NOI2009]植物大战僵尸,主要包括P2805 [NOI2009]植物大战僵尸使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

最大权闭合子图裸题、环上的点要去掉。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

const int MAXN = 32, INF = 0x3f3f3f3f;

class Graph{
	private:
		struct Edge{
			int to, next, c;
		}edge[1 << 20];
		
		int cnt, head[1 << 10];
		
		void add(int from, int to, int c){
			edge[++cnt].to = to;
			edge[cnt].c = c;
			edge[cnt].next = head[from];
			head[from] = cnt;
		}
		
		int dep[1 << 10];
		
		bool bfs(void){
			std::queue<int> q; q.push(s);
			std::memset(dep, 0, sizeof dep); dep[s] = 1;
			while(!q.empty()){
				int node = q.front(); q.pop();
				for(int i = head[node]; i != -1; i = edge[i].next){
					if(edge[i].c && !dep[edge[i].to])
						dep[edge[i].to] = dep[node] + 1, q.push(edge[i].to);
				}
			}
			return dep[t];
		}
		
		int cur[1 << 10];
		
		int dfs(int node, int flow){
			if(node == t || !flow)
				return flow;
			int stream = 0, f;
			for(int i = cur[node]; i != -1; i = edge[i].next){
				cur[node] = i;
				if(
					dep[edge[i].to] == dep[node] + 1
					&& (f = dfs(edge[i].to, std::min(flow, edge[i].c)))
				){
					edge[i].c -= f, edge[i ^ 1].c += f;
					flow -= f, stream += f;
					if(!flow)
						break;
				}
			}
			return stream;
		}
		
	public:
		int s, t;
		
		Graph(){
			std::memset(head, -1, sizeof head);
			cnt = -1; 
		}
		
		void set(int src, int trm){
			s = src, t = trm;
		}
		
		void add_edge(int from, int to, int c){
			add(from, to, c);
			add(to, from, 0);
		}
		
		int flow(void){
			int f = 0;
			while(bfs()){
				std::memcpy(cur, head, sizeof head);
				f += dfs(s, INF);
			}
			return f;
		}
}G;

int n, m;
int ind, id[MAXN][MAXN], score[MAXN * MAXN];

struct Edge{
	int to, next;
}edge[1 << 20];

int cnt, head[1 << 10];

inline void add(int from, int to){
	edge[++cnt].to = to;
	edge[cnt].next = head[from];
	head[from] = cnt;
}

int ans;

int dim[MAXN * MAXN];
bool isIn[MAXN * MAXN];

void topo_sort(void){
	std::queue<int> q;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
			for(int k = head[id[i][j]]; k; k = edge[k].next)
				++dim[edge[k].to];
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
			if(!dim[id[i][j]])
				q.push(id[i][j]), isIn[id[i][j]] = true;
	while(!q.empty()){
		int node = q.front(); q.pop();
		for(int i = head[node]; i; i = edge[i].next){
			--dim[edge[i].to];
			if(!dim[edge[i].to])	
				q.push(edge[i].to), isIn[edge[i].to] = true;
		}
	}
}

int main(){
	std::scanf("%d%d", &n, &m);
	G.s = ++ind, G.t = ++ind;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
			id[i][j] = ++ind;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j){
			int w;
			std::scanf("%d%d", score + id[i][j], &w);
			for(int k = 1; k <= w; ++k){
				int u, v;
				std::scanf("%d%d", &u, &v);
				++u, ++v;
				add(id[i][j], id[u][v]);
			}
			if(j != 1)
				add(id[i][j], id[i][j - 1]);
		}
	topo_sort();
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
			if(isIn[id[i][j]]){
				if(score[id[i][j]] > 0)
					G.add_edge(G.s, id[i][j], +score[id[i][j]]), ans += score[id[i][j]];
				else if(score[id[i][j]] < 0)
					G.add_edge(id[i][j], G.t, -score[id[i][j]]);
				for(int k = head[id[i][j]]; k; k = edge[k].next)
					if(isIn[edge[k].to])
						G.add_edge(edge[k].to, id[i][j], INF);
			}
	ans -= G.flow();
	std::printf("%d\n", ans);
	return 0;
}

原文地址:https://www.cnblogs.com/natsuka/p/12933415.html