zoukankan      html  css  js  c++  java
  • Luogu P3355 骑士共存问题

    题目链接 (Click) (Here)

    二分图最大独立集。对任意两个可以相互攻击的点,我们可以选其中一个。对于不会互相攻击的,可以全部选中。所以我们只需要求出最大匹配,根据定理,二分图最大独立集等于点数减去最大匹配,就得到了答案。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 80010;
    const int M = 800010;
    const int INF = 0x3f3f3f3f;
    
    int n, m, ban[210][210];
    int cnt = -1, head[N];
    int mv[8][2] = {{2, 1},{2, -1},{1, 2},{1, -2},{-2, 1},{-2, -1},{-1, 2},{-1, -2}};
    
    bool in_map (int x, int y) {return 1 <= x && x <= n && 1 <= y && y <= n;}
    
    struct edge {
    	int nxt, to, f;
    }e[M];
    
    void add_edge (int from, int to, int flw) {
    	e[++cnt].nxt = head[from];
    	e[cnt].to = to;
    	e[cnt].f = flw;
    	head[from] = cnt;
    }
    
    void add_len (int u, int v, int f) {
    	add_edge (u, v, f);
    	add_edge (v, u, 0);
    }
    
    int nd1 (int x, int y) {return n * n * 0 + (x - 1) * n + y;}
    int nd2 (int x, int y) {return n * n * 1 + (x - 1) * n + y;}
    
    queue <int> q;
    int cur[N], deep[N];
    
    bool bfs (int s, int t) {
    	memcpy (cur, head, sizeof (head));
    	memset (deep, 0x3f, sizeof (deep));
    	q.push (s); deep[s] = 0;
    	while (!q.empty ()) {
    		int u = q.front (); q.pop ();
    		for (int i = head[u]; ~i; i = e[i].nxt) {
    			int v = e[i].to;
    			if (deep[v] == INF && e[i].f) {
    				deep[v] = deep[u] + 1;
    				q.push (v);
    			}
    		}
    	}
    	return deep[t] != INF;
    }
    
    int dfs (int u, int t, int lim) {
    	if (u == t || !lim) {
    		return lim;
    	}
    	int tmp = 0, flow = 0;
    	for (int &i = cur[u]; ~i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (deep[v] == deep[u] + 1) {
    			tmp = dfs (v, t, min (lim, e[i].f));
    			lim -= tmp;
    			flow += tmp;
    			e[i ^ 0].f -= tmp;
    			e[i ^ 1].f += tmp;
    			if (!lim) break;
    		}
    	}
    	return flow;
    }
    
    int main () {
    	memset (head, -1, sizeof (head));
    	cin >> n >> m;
    	for (int i = 1; i <= m; ++i) {
    		int x, y;
    		cin >> x >> y;
    		ban[x][y] = true;
    	}
    	int s = n * n * 2 + 1, t = n * n * 2 + 2;
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= n; ++j) {
    			if (ban[i][j]) continue;
    			add_len (s, nd1 (i, j), 1);
    			add_len (nd2 (i, j), t, 1);
    			for (int k = 0; k < 8; ++k) {
    				int tx = i + mv[k][0];
    				int ty = j + mv[k][1];
    				if (in_map (tx, ty) && !ban[tx][ty]) {
    					add_len (nd1 (i, j), nd2 (tx, ty), 1);
    				}
    			}
    		}
    	}
    	int max_flow = 0;
    	while (bfs (s, t)) {
    		getchar ();
    		max_flow += dfs (s, t, INF);
    	}
    	// printf ("max_flow = %d
    ", max_flow);
    	cout << n * n - m - max_flow / 2 << endl;
    } 
    
    
  • 相关阅读:
    Git理解
    Java基础之四、字符和字符串 异常处理
    魔方第三层复原技巧
    Java基础之三、类的特性和接口
    Java基础之二、类的知识
    Java基础之一、入门知识
    UML之三、建模元素(2)
    看懂棒球-规则、数据
    【转载】自助终端设备安全剖析 (深度好文)
    CVE-2017-12615 Tomcat远程代码执行
  • 原文地址:https://www.cnblogs.com/maomao9173/p/10479419.html
Copyright © 2011-2022 走看看