考虑把答案进行转化,通过分矩形条,我们能去掉一些夹在#之间的边

那么答案= #个数 - 能去掉的边个数

但去掉是有限制的,同一个#格子的横边和竖边不能同时去掉

把边转化成点,限制变成边。

横竖边的点 和 限制 构成了一个二分图。

问题转化成求这个二分图的最大权独立集!!

上dinic就行了

  1 #include <set>
2 #include <vector>
3 #include <cstdio>
4 #include <cstring>
5 #include <algorithm>
6 #define ull unsigned long long
7 #define ll long long
8 using namespace std;
9 const int N1=200+5, inf=0x3f3f3f3f;
10 int xx[]={-1,1,0,0}, yy[]={0,0,-1,1};
11
12 template <typename _T> void read(_T &ret)
13 {
14 ret=0; _T fh=1; char c=getchar();
15 while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); }
16 while(c>='0'&&c<='9'){ ret=ret*10+c-'0'; c=getchar(); }
17 ret=ret*fh;
18 }
19
20 const int N2=8e4+5, M2=N2*8;
21 struct EDGE{
22 int to[M2],nxt[M2],flow[M2],head[N2],cte;
23 void ae(int u,int v,int f)
24 { cte++; to[cte]=v, nxt[cte]=head[u]; flow[cte]=f; head[u]=cte; }
25 void adde(int u,int v,int f)
26 { ae(u,v,f); ae(v,u,0); }
27 }e;
28 int idx(char c){ return c-'0'; }
29
30 int n,m,S,T;
31 int xid[N1][N1],yid[N1][N1],tot;
32 char str[N1][N1];
33
34 int que[N2],hd,tl,cur[N2],dep[N2];
35 int bfs()
36 {
37 int x,j,v;
38 memset(dep,-1,sizeof(dep)); memcpy(cur,e.head,sizeof(cur));
39 hd=1,tl=0; que[++tl]=S; dep[S]=0;
40 while(hd<=tl)
41 {
42 x=que[hd++];
43 for(int j=e.head[x];j;j=e.nxt[j])
44 {
45 v=e.to[j]; if(e.flow[j]<=0||dep[v]!=-1) continue;
46 dep[v]=dep[x]+1; que[++tl]=v;
47 }
48 }
49 return dep[T]!=-1;
50 }
51 int dfs(int x,int limit)
52 {
53 int j,v,flow,ans=0;
54 if(!limit||x==T) return limit;
55 for(j=cur[x];j;j=e.nxt[j])
56 {
57 cur[x]=j; v=e.to[j];
58 if(dep[v]==dep[x]+1 && (flow=dfs(v,min(limit,e.flow[j]))) )
59 {
60 limit-=flow; ans+=flow;
61 e.flow[j]-=flow; e.flow[j^1]+=flow;
62 if(!limit) break;
63 }
64 }
65 return ans;
66 }
67 int Dinic()
68 {
69 int ans=0,flow;
70 while(bfs())
71 {
72 flow=dfs(S,inf);
73 if(!flow) break;
74 ans+=flow;
75 }
76 return ans;
77 }
78
79 int main()
80 {
81 // freopen("a.in","r",stdin);
82 read(n); read(m);
83 for(int i=1;i<=n;i++) scanf("%s",str[i]+1);
84 e.cte=1;
85 for(int i=1;i<n;i++) for(int j=1;j<=m;j++) xid[i][j]=++tot;
86 for(int i=1;i<=n;i++) for(int j=1;j<m;j++) yid[i][j]=++tot;
87 S=++tot; T=++tot;
88 for(int i=1;i<n;i++) for(int j=1;j<=m;j++) e.adde(S,xid[i][j],1);
89 for(int i=1;i<=n;i++) for(int j=1;j<m;j++) e.adde(yid[i][j],T,1);
90 int suma=0,sumb=0;
91 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(str[i][j]=='#')
92 {
93 suma++;
94 int id[4]={-1,-1,-1,-1};
95 for(int k=0;k<4;k++) if(str[i+xx[k]][j+yy[k]]=='#')
96 {
97 if(k==0) id[k]=xid[i-1][j];
98 if(k==1) id[k]=xid[i][j];
99 if(k==2) id[k]=yid[i][j-1];
100 if(k==3) id[k]=yid[i][j];
101 sumb++;
102 }
103 for(int x=0;x<=1;x++) for(int y=2;y<=3;y++) if(id[x]!=-1&&id[y]!=-1)
104 {
105 e.adde(id[x],id[y],1);
106 }
107 }
108 sumb>>=1;
109 sumb-=Dinic();
110 printf("%d\n",suma-sumb);
111 return 0;
112 }

CF1404E Bricks (最大权独立集)的更多相关文章

  1. HDU 1569 方格取数(2)(最大流最小割の最大权独立集)

    Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大.   ...

  2. hdu 1569 最大权独立集

    /*最大点权独立集=sum-最小点权覆盖*/ #include<stdio.h> #include<string.h> #include<queue> using ...

  3. BZOJ3275Number——二分图最大权独立集

    题目描述 有N个正整数,需要从中选出一些数,使这些数的和最大.若两个数a,b同时满足以下条件,则a,b不能同时被选1:存在正整数C,使a*a+b*b=c*c2:gcd(a,b)=1 输入 第一行一个正 ...

  4. HDU 1565:方格取数(1)(最大点权独立集)***

    http://acm.hdu.edu.cn/showproblem.php?pid=1565 题意:中文. 思路:一个棋盘,要使得相邻的点不能同时选,问最大和是多少,这个问题就是最大点权独立集. 可以 ...

  5. BZOJ3548 : [ONTAK2010]Party

    首先将朋友通过并查集缩起来,因为$P\geq\frac{n(n-1)}{3}$,所以最后最多剩下$46$个点. 将自相矛盾的点删掉,就变成求最大权独立集问题,这等于求补图的最大团. 然后直接用Bron ...

  6. 最小割 总结&&做题记录

    模型要点: 1.一般适用于二取一问题或者01规划. 2.利用最小割=最大流,转化为最大流求之. 建议阅读胡伯涛的论文 <<最小割模型在信息学竞赛的应用>>,有精彩有序的证明和各 ...

  7. LightOJ1360 Skyscraper(DP)

    题目大概是,一个数轴上n个线段,每个线段都有起始坐标.长度和权值,问从中取出没有公共交点的线段的最大权和. 取k次是个经典的最小费用最大流问题,不过这题建容量网络有20W个点,离散化最多也要6W个点, ...

  8. bzoj 3275 Number(最小割)

    [题意] 给定n个数,要求选出一些数满足 1.存在c,a*a+b*b=c*c 2.gcd(a,b)=1  使得和最大. [思路] 二分图的最大权独立集(可以这么叫么QAQ 先拆点,对于不满足条件的两个 ...

  9. bzoj3275

    容易想到是最小割(最大权独立集)然后每个数拆成两个点,不能同时选的之间连边跑最小割,最后答案=总数-mincut/2 因为这样建图将流量变成了原来的两倍 当然这道题更好的建图方法是分成奇数和偶数两个集 ...

随机推荐

  1. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  2. 编译安装 tree 命令

    文章目录 下载源码包 编译源码包 tree下载地址:http://mama.indstate.edu/users/ice/tree/ Centos发行版,可以直接使用命令 yum -y install ...

  3. Java并发基础之AbstractQueuedSynchronizer(AQS)

    AbstractQueuedSynchronizer同步器是实现JUC核心基础组件,因为 定义了一套多线程访问共享资源的同步器框架.前面几篇文章中JUC同步工具中都利用AQS构建自身的阻塞类.AQS解 ...

  4. json系列(二)cjson,rapidjson,yyjson大整数解析精度对比

    前言上一篇介绍了3种json解析工具的使用方法,对于基础数据的解析没有任何问题.我们传输的json数据里有unsigned long型数据,需要借助json解析工具得到正确的unsigned long ...

  5. 【C#操作符】typeof 和 is 运算符执行的类型检查之间的差异

    typeof 运算符也能用于公开的泛型类型.具有不止一个类型参数的类型的规范中必须有适当数量的逗号.不能重载 typeof 运算符. is 可以检测和父类是否兼容,typeof责不能 public c ...

  6. 【Oracle】PLSQL如何更新、提交数据库中数据

    转至:https://blog.csdn.net/Bee_AI/article/details/89279612 Oracle更新单表数据时,一般使用SELECT--FOR UPDATE语句,这条语句 ...

  7. 面向对象编程(C++篇1)——引言

    目录 1. 概述 2. 详论 2.1. 类与对象 2.2. 数据类型 3. 目录 1. 概述 现代C++与最原始的版本已经差不多是两种不同的语言了.不断发展的C++标准给C++这门语言带来了更多的范式 ...

  8. LeetCode-001-两数之和

    两数之和 题目描述:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标. 你可以假设每种输入只会对应一个答 ...

  9. 清华大学ucore操作系统课笔记

    操作系统 清华大学ucore操作系统课笔记 全文思维导图 1. 操作系统概述 1.1 什么是操作系统? 操作系统的定义 没有公认的精确定义 一个控制程序 一个系统软件 控制程序执行过程,防止错误和计算 ...

  10. GateWay配置使用

    是什么 Cloud全家桶中有个很重要的组建就是网关,在1.x版本中都是采用的Zuul网关 但在2.X版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关替代Zuul Sprin ...