zoukankan      html  css  js  c++  java
  • 【Vijos 1607】【NOI 2009】植物大战僵尸

    https://vijos.org/p/1607
    vijos界面好漂亮O(∩_∩)O~~
    对于一个植物x,和一个它保护的植物y,连一条边<x,y>表示x保护y,对于每个植物再向它左方的植物也连一条边,很明显能连出一个图,图中的边<x,y>的含义为如果要吃y,就必须先吃x。
    这个图的强连通分量中的植物永远不会被吃,而且强联通分量中的植物连出去的边能到达的任何植物都不会被吃。
    本来想先tarjan然后再dfs,然后DaD3zZ用拓扑序教我做人qwq
    所有入度为0的点可以被吃,入读为0的点连出去的且不再强连通分量中的点也可以被吃,拓扑一下就好了。
    把可以被吃的点拿出来就是一个最大权闭合图问题了,最小割解决。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N = 633;
    const int inf = 0x7fffffff;
    
    bool can[N];
    int cur[N], qu[N], id[23][33], n, m, cnt = 0, tot = 0, score[N], point[N], point2[N], in[N];
    
    struct node {int nxt, to, c;} E[N * N];
    struct node2 {int nxt, to;} G[N * N];
    
    void ins(int u, int v, int c) {E[++cnt] = (node) {point[u], v, c}; point[u] = cnt;}
    void ins2(int u, int v) {G[++cnt] = (node2) {point2[u], v}; point2[u] = cnt; ++in[v];}
    
    int d[N];
    bool BFS(int s, int t) {
    	memset(d, 0, sizeof(int) * (t + 1));
    	int p = 0, q = 1; qu[1] = s; d[s] = 1;
    	while (p != q) {
    		int u = qu[++p];
    		for (int i = point[u]; i; i = E[i].nxt)
    			if (E[i].c && d[E[i].to] == 0) {
    				d[E[i].to] = d[u] + 1;
    				qu[++q] = E[i].to;
    			}
    	}
    	return d[t];
    }
    
    int S, T;
    int dfs(int u, int a) {
    	if (u == T || !a) return a;
    	int f, flow = 0;
    	for (int &i = cur[u]; i; i = E[i].nxt)
    		if (d[E[i].to] == d[u] + 1 && (f = dfs(E[i].to, min(a, E[i].c)))) {
    			flow += f; E[i].c -= f; E[i ^ 1].c += f; a -= f;
    			if (!a) break;
    		}
    	return flow;
    }
    
    int dinic(int s, int t) {
    	int flow = 0;
    	while (BFS(s, t)) {
    		for (int i = 1; i <= t; ++i) cur[i] = point[i];
    		flow += dfs(s, inf);
    	}
    	return flow;
    }
    
    int main() {
    	scanf("%d%d", &n, &m);
    	int s, x, y;
    	for (int i = 0; i < n; ++i)
    		for (int j = 0; j < m; ++j)
    			id[i][j] = ++tot;
    	for (int i = 0; i < n; ++i)
    		for (int j = 0; j < m; ++j) {
    			scanf("%d%d", score + id[i][j], &s);
    			for (int k = 0; k < s; ++k) {
    				scanf("%d%d", &x, &y);
    				ins2(id[i][j], id[x][y]);
    			}
    		}
    	for (int i = 0; i < n; ++i)
    		for (int j = 1; j < m; ++j)
    			ins2(id[i][j], id[i][j - 1]);
    	
    	int head = 0, tail = 0;
    	for (int i = 0; i < n; ++i)
    		if (in[id[i][m - 1]] == 0)
    			qu[++tail]= id[i][m - 1];
    	
    	while (head != tail) {
    		int u = qu[++head]; can[u] = true;
    		for (int i = point2[u]; i; i = G[i].nxt)
    			if (--in[G[i].to] == 0)
    				qu[++tail] = G[i].to;
    	}
    	
    	cnt = 1;
    	for (int i = 1; i <= tot; ++i)
    		if (can[i])
    			for (int j = point2[i]; j; j = G[j].nxt)
    				if (can[G[j].to]) {
    					ins(G[j].to, i, inf);
    					ins(i, G[j].to, 0);
    				}
    	
    	int ans = 0; S = tot + 1, T = S + 1;
    	for (int i = 1; i <= tot; ++i)
    		if (can[i]) {
    			if (score[i] > 0) {
    				ans += score[i];
    				ins(S, i, score[i]);
    				ins(i, S, 0);
    			} else if (score[i] < 0) {
    				ins(i, T, -score[i]);
    				ins(T, i, 0);
    			}
    		}
    	printf("%d
    ", ans - dinic(S, T));
    	return 0;
    }
    
  • 相关阅读:
    springsecurity 注解开发
    springsecurity 授权
    【ElasticSearch】集群搭建
    【CentOS7.9】防火墙配置使用
    【CentOS7.9】创建及挂载共享文件夹
    查看Linux发行版
    【Spring Cloud】spring-cloud2020和spring-cloud-alibaba2021问题记录
    【Spring Cloud】spring.factories
    三剑客-----grep
    git安装
  • 原文地址:https://www.cnblogs.com/abclzr/p/6635197.html
Copyright © 2011-2022 走看看