[BZOJ4808] 马(最大独立集,最大流)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4808

题意:其实就是找出一个点集的子集,使得这个子集中的点互不相连。求这个子集规模最大。

就是最大独立集。点好多,有200*200个。所以用dinic优化了下。

最大独立集=N-最大匹配,最大匹配=最大流,所以最大独立集=N-最大流。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3
  4 //下标从0开始
  5 typedef struct Edge {
  6     int u, v, w, next;
  7 }Edge;
  8
  9 const int inf = 0x7f7f7f7f;
 10 const int maxn = 400400;
 11 const int maxm = 220;
 12
 13 int cnt, dhead[maxn];
 14 int cur[maxn], dd[maxn];
 15 Edge dedge[maxn<<1];
 16 // bool vis[maxn]; // 记录经过的点
 17 int S, T, N;
 18
 19 void init() {
 20     memset(dhead, -1, sizeof(dhead));
 21     for(int i = 0; i < maxn; i++) dedge[i].next = -1;
 22     S = 0; cnt = 0;
 23 }
 24
 25 void adde(int u, int v, int w, int c1=0) {
 26     dedge[cnt].u = u; dedge[cnt].v = v; dedge[cnt].w = w;
 27     dedge[cnt].next = dhead[u]; dhead[u] = cnt++;
 28     dedge[cnt].u = v; dedge[cnt].v = u; dedge[cnt].w = c1;
 29     dedge[cnt].next = dhead[v]; dhead[v] = cnt++;
 30 }
 31
 32 bool bfs(int s, int t, int n) {
 33     // memset(vis, 0, sizeof(vis));
 34     queue<int> q;
 35     for(int i = 0; i < n; i++) dd[i] = inf;
 36     dd[s] = 0;
 37     q.push(s);
 38     while(!q.empty()) {
 39         int u = q.front(); q.pop();
 40         for(int i = dhead[u]; ~i; i = dedge[i].next) {
 41             if(dd[dedge[i].v] > dd[u] + 1 && dedge[i].w > 0) {
 42                 dd[dedge[i].v] = dd[u] + 1;
 43                 // vis[dedge[i].v] = 1;
 44                 if(dedge[i].v == t) return 1;
 45                 q.push(dedge[i].v);
 46             }
 47         }
 48     }
 49     return 0;
 50 }
 51
 52 int dinic(int s, int t, int n) {
 53     int st[maxn], top;
 54     int u;
 55     int flow = 0;
 56     while(bfs(s, t, n)) {
 57         for(int i = 0; i < n; i++) cur[i] = dhead[i];
 58         u = s; top = 0;
 59         while(cur[s] != -1) {
 60             if(u == t) {
 61                 int tp = inf;
 62                 for(int i = top - 1; i >= 0; i--) {
 63                     tp = min(tp, dedge[st[i]].w);
 64                 }
 65                 flow += tp;
 66                 for(int i = top - 1; i >= 0; i--) {
 67                     dedge[st[i]].w -= tp;
 68                     dedge[st[i] ^ 1].w += tp;
 69                     if(dedge[st[i]].w == 0) top = i;
 70                 }
 71                 u = dedge[st[top]].u;
 72             }
 73             else if(cur[u] != -1 && dedge[cur[u]].w > 0 && dd[u] + 1 == dd[dedge[cur[u]].v]) {
 74                 st[top++] = cur[u];
 75                 u = dedge[cur[u]].v;
 76             }
 77             else {
 78                 while(u != s && cur[u] == -1) {
 79                     u = dedge[st[--top]].u;
 80                 }
 81                 cur[u] = dedge[cur[u]].next;
 82             }
 83         }
 84     }
 85     return flow;
 86 }
 87
 88 const int dx[11] = {-1,1,2,2,1,-1,-2,-2};
 89 const int dy[11] = {-2,-2,-1,1,2,2,1,-1};
 90 int n, m;
 91 int mp[maxm][maxm];
 92
 93 inline bool bound(int x, int y) { return x >= 1 && x <= n && y >= 1 && y <= m;}
 94 inline int id(int x, int y) { return (x - 1) * m + y; }
 95
 96 int main() {
 97     // freopen("in", "r", stdin);
 98     while(~scanf("%d%d",&n,&m)) {
 99         init();
100         S = 0, T = 2 * id(n, m) + 1, N = T + 1;
101         for(int i = 1; i <= n; i++) {
102             for(int j = 1; j <= m; j++) {
103                 adde(S, id(i,j), 1);
104                 adde(id(n,m)+id(i,j), T, 1);
105                 scanf("%d", &mp[i][j]);
106             }
107         }
108         int tot = 0;
109         for(int i = 1; i <= n; i++) {
110             for(int j = 1; j <= m; j++) {
111                 if(mp[i][j] == 1) continue;
112                 tot++;
113                 for(int k = 0; k < 8; k++) {
114                     int x = i + dx[k];
115                     int y = j + dy[k];
116                     if(!bound(x, y)) continue;
117                     if(!mp[x][y]) adde(id(i,j), id(n,m)+id(x,y), inf);
118                 }
119             }
120         }
121         printf("%d\n", tot - dinic(S, T, N)/2);
122     }
123     return 0;
124 }
时间: 2024-10-03 14:42:01

[BZOJ4808] 马(最大独立集,最大流)的相关文章

bzoj4808: 马 &amp; bzoj3175: [Tjoi2013]攻击装置 (黑白染色+最小割)

bzoj4808: 马 & bzoj3175: [Tjoi2013]攻击装置 题目:传送门 简要题意: 和n皇后问题差不多,但是这里是每个棋子走日子,而且有些格子不能放棋子.求最多能放多少个棋子. 题解: 双倍经验好评 之前看过机房神犇做...有点印象是最小割. 但是直接割的话不会...要应用到黑白染色: 最开始我想递归染色,也就是取一个开始染,然后递归下去... 波老师说会错ORZ...因为感觉递归的情况不好掌握,有可能会重复染色... 结果有一个肥肠巧妙的方法...直接相邻的染为不同颜色 之

hihocoder 1158 质数相关 (二分图最大独立集 最大流ISAP求解)

#1158 : 质数相关 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 两个数a和 b (a<b)被称为质数相关,是指a × p = b,这里p是一个质数.一个集合S被称为质数相关,是指S中存在两个质数相关的数,否则称S为质数无关.如{2, 8, 17}质数无关,但{2, 8, 16}, {3, 6}质数相关.现在给定一个集合S,问S的所有质数无关子集中,最大的子集的大小. 输入 第一行为一个数T,为数据组数.之后每组数据包含两行. 第一行为N,为集合S的大小.第二

BZOJ4808: 马&amp;BZOJ3175: [Tjoi2013]攻击装置

BZOJ3175 Description 给定一个01矩阵,其中你可以在0的位置放置攻击装置.每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1), (x+1,y+2),(x+2,y+1)求在装置互不攻击的情况下,最多可以放置多少个装置. Input 第一行一个整数N,表示矩阵大小为N*N.接下来N行每一行一个长度N的01串,表示矩阵. Output 一个整数,表示在

Atitit 如何利用先有索引项进行查询性能优化

1.1. 再分析的话就是我们所写的查询条件,其实大部分情况也无非以下几种:1 1.2. 范围查找 动态索引查找1 1.2.1. 索引联合 所谓的索引联合,就是根据就是根据筛选条件的不同,拆分成不同的条件,去匹配不同的索引项.2 1.3. 索引交叉2 1.1. 再分析的话就是我们所写的查询条件,其实大部分情况也无非以下几种: 1.等于谓词:select [email protected] 2.比较谓词:select ...where...column> or < or  <> or

SQL Server调优系列基础篇(索引运算总结)

原文:SQL Server调优系列基础篇(索引运算总结) 前言 上几篇文章我们介绍了如何查看查询计划.常用运算符的介绍.并行运算的方式,有兴趣的可以点击查看. 本篇将分析在SQL Server中,如何利用先有索引项进行查询性能优化,通过了解这些索引项的应用方式可以指导我们如何建立索引.调整我们的查询语句,达到性能优化的目的. 闲言少叙,进入本篇的正题. 技术准备 基于SQL Server2008R2版本,利用微软的一个更简洁的案例库(Northwind)进行解析. 简介 所谓的索引应用就是在我们

【自用】OI知识点总结

链接: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/45216967"); } 看目录就好了.不用看具体部分 网络流 二分图 最大匹配 最小点覆盖 最小边覆盖 最小路径覆盖 最大独立集 最大流 上下界最大流 最小割 全局最小割 费用流 上下界费用流 线性规划转费用流 最大权闭合图 RMQ

Accelerated C++学习笔记5—&lt;组织程序和数据&gt;

第4章  组织程序和数据 从前面的学习中,我们可以发现程序并不是我们所想的那么简短,他们都有一个共同的特性,那就是 1)都能解决某些特定类型的问题 2)与其他的大多数工具都互相独立 3)都具有一个自己的名称 C++中提供两种基本的方法来让我们组织大型的程序,函数(子程序)和数据结构. 1.组织计算 1)计算总成绩 子函数grade <span style="font-family:KaiTi_GB2312;">//根据学生的期中考试.期末考试.家庭作业成绩来计算总成绩 do

SQL Server调优系列 - 索引运算总结

前言 上几篇文章我们介绍了如何查看查询计划.常用运算符的介绍.并行运算的方式,有兴趣的可以点击查看. 本篇将分析在SQL Server中,如何利用先有索引项进行查询性能优化,通过了解这些索引项的应用方式可以指导我们如何建立索引.调整我们的查询语句,达到性能优化的目的. 闲言少叙,进入本篇的正题. 技术准备 基于SQL Server2008R2版本,利用微软的一个更简洁的案例库(Northwind)进行解析. 简介 所谓的索引应用就是在我们日常写的T-SQL语句中,如何利用现有的索引项,再分析的话

中国历史十大经典战役

中国历史十大经典战役  NO.1 牧野之战 "牧野洋洋,--时维鹰扬,凉彼武王肆伐大商,会期清明"现代人根据史书记载的天象,甚至推算出了具体时间是公元前1106年2月4日.周武王统率兵车300乘,虎贲3000人,甲士4万5千人,汇集各部落的兵力,大破商军的共约17万人于牧野. NO.2 城濮之战 面对锋芒必露的楚军,晋文公选择"退避三舍",然后集中优势兵力对于楚军3路兵马实行各个击破,最后战斗以晋文公在践土朝觐周王,会盟诸侯结束. NO.3 长平之战 秦赵为了上党的