zoukankan      html  css  js  c++  java
  • bzoj1565 植物大战僵尸

    题目链接

    思路

    如果想消灭掉一个植物,那么必须先消灭掉左右能保护这个植物的植物。这就成了最大权闭合子图的模板题了。
    有两个需要注意的地方。
    第一个就是,能保护当前植物的植物还有当前植物右面的所有植物。
    第二个就是,在环里的植物或者是被在环里的植物所保护的植物是无法消灭的。
    所以先拓扑一下,找出所有可能被消灭的植物,然后按照最大权闭合子图的做法做就行了。

    代码

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<cstring>
    #include<vector>
    #include<bitset>
    using namespace std;
    typedef long long ll;
    #define num(x,y) y + (x - 1) * m
    const int N = 100000,M = 1000000,INF = 1e9;
    vector<int>E[N];
    ll read() {
    	ll x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9') {
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9') {
    		x=x*10+c-'0';
    		c=getchar();
    	}
    	return x*f;
    }
    
    struct node {
    	int v,nxt,w;
    }e[M];
    int head[N],ejs = 1;
    void add(int u,int v,int w) {
    	e[++ejs].v = v;e[ejs].w = w;e[ejs].nxt = head[u];head[u] = ejs;
    	e[++ejs].v = u;e[ejs].w = 0;e[ejs].nxt = head[v];head[v] = ejs;
    }
    int n,m,w[N],du[N];
    queue<int>q;
    int dep[N];
    int S,T;
    int bfs() {
    	memset(dep,0,sizeof(dep));
    	while(!q.empty()) q.pop();
    	dep[S] = 1;q.push(S);
    	while(!q.empty()) {
    		int u = q.front();q.pop();
    		for(int i = head[u];i;i = e[i].nxt) {
    			int v = e[i].v;
    			if(!dep[v] && e[i].w) {
    				q.push(v);
    				dep[v] = dep[u] + 1;
    				if(v == T) return 1;
    			}
    	}
    	}
    	return 0;
    }
    int cur[N];
    int dfs(int u,int now) {
    	if(u == T) return now;
    	int ret = 0;
    	for(int &i = cur[u];i;i = e[i].nxt) {
    		int v = e[i].v;
    		if(dep[v] == dep[u] + 1 && e[i].w) {
    			int k = dfs(v,min(now - ret,e[i].w));
    			e[i].w -= k;
    			e[i ^ 1].w += k;
    			ret += k;
    			if(now == ret) return ret;
    		}
    	}
    	return ret;
    }
    int dinic() {
    	int ans = 0;
    	while(bfs()) {
    		memcpy(cur,head,sizeof(cur));
    		ans += dfs(S,INF);
    	}
    	return ans;
    }
    int main() {
    	n = read(),m = read();
    	S = n * m + 1,T = S + 1;
    	for(int i = 1;i <= n;++i) {
    		for(int j = 1;j <= m;++j) {
    			w[num(i,j)] = read();int k = read();
    			for(int z = 1;z <= k;++z) {
    				int x = read() + 1,y = read() + 1;
    				E[num(i,j)].push_back(num(x,y));
    				du[num(x,y)]++;
    			}
    		}
    	}
    	for(int i = 1;i <= n;++i) {
    		for(int j = 2;j <= m;++j) {
    			E[num(i,j)].push_back(num(i,j - 1));
    			du[num(i,j-1)]++;
    		}
    	}
    	for(int i = 1;i <= n * m;++i) if(!du[i]) q.push(i);
    	while(!q.empty()) {
    		int u = q.front();q.pop();
    		int k = E[u].size();
    		for(int i = 0; i < k;++i) {
    			int v = E[u][i];
    			du[v]--;
    			if(!du[v]) q.push(v);
    		}
    	}
    	int ans = 0;
    	for(int i = 1;i <= n * m;++i) {
    		if(!du[i]) {
    			if(w[i] >= 0) add(S,i,w[i]),ans += w[i];
    			else add(i,T,-w[i]);
    			int k = E[i].size();
    			for(int j = 0;j < k;++j) {
    				int v = E[i][j];
    				if(!du[v]) add(v,i,INF);
    			}
    		}
    	}
    	cout<<ans - dinic();
    	return 0;
    }
    
  • 相关阅读:
    Spring编译AOP项目报错
    Intellij新建Spring项目引入用户目录下的Spring jar包
    python如何安装第三方库
    sizeof and strlen整理
    数轴上从左到右有n个点a[0],a[1]…,a[n-1],给定一根长度为L的绳子,求绳子最多能覆盖其中的几个点。要求算法复杂度为o(n)。
    百度笔试题--最长回文字串
    微软笔试题
    人群智商差不多,是什么引起了差距?
    低层次“努力学习”和学习的本质
    集成 solr6.5.1到 tomcat7(8) 中 (解决java.lang.NoSuchMethodError问题)
  • 原文地址:https://www.cnblogs.com/wxyww/p/10356203.html
Copyright © 2011-2022 走看看