CF1404E Bricks (最大权独立集)
考虑把答案进行转化,通过分矩形条,我们能去掉一些夹在#之间的边
那么答案= #个数 - 能去掉的边个数
但去掉是有限制的,同一个#格子的横边和竖边不能同时去掉
把边转化成点,限制变成边。
横竖边的点 和 限制 构成了一个二分图。
问题转化成求这个二分图的最大权独立集!!
上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 (最大权独立集)的更多相关文章
- HDU 1569 方格取数(2)(最大流最小割の最大权独立集)
Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大. ...
- hdu 1569 最大权独立集
/*最大点权独立集=sum-最小点权覆盖*/ #include<stdio.h> #include<string.h> #include<queue> using ...
- BZOJ3275Number——二分图最大权独立集
题目描述 有N个正整数,需要从中选出一些数,使这些数的和最大.若两个数a,b同时满足以下条件,则a,b不能同时被选1:存在正整数C,使a*a+b*b=c*c2:gcd(a,b)=1 输入 第一行一个正 ...
- HDU 1565:方格取数(1)(最大点权独立集)***
http://acm.hdu.edu.cn/showproblem.php?pid=1565 题意:中文. 思路:一个棋盘,要使得相邻的点不能同时选,问最大和是多少,这个问题就是最大点权独立集. 可以 ...
- BZOJ3548 : [ONTAK2010]Party
首先将朋友通过并查集缩起来,因为$P\geq\frac{n(n-1)}{3}$,所以最后最多剩下$46$个点. 将自相矛盾的点删掉,就变成求最大权独立集问题,这等于求补图的最大团. 然后直接用Bron ...
- 最小割 总结&&做题记录
模型要点: 1.一般适用于二取一问题或者01规划. 2.利用最小割=最大流,转化为最大流求之. 建议阅读胡伯涛的论文 <<最小割模型在信息学竞赛的应用>>,有精彩有序的证明和各 ...
- LightOJ1360 Skyscraper(DP)
题目大概是,一个数轴上n个线段,每个线段都有起始坐标.长度和权值,问从中取出没有公共交点的线段的最大权和. 取k次是个经典的最小费用最大流问题,不过这题建容量网络有20W个点,离散化最多也要6W个点, ...
- bzoj 3275 Number(最小割)
[题意] 给定n个数,要求选出一些数满足 1.存在c,a*a+b*b=c*c 2.gcd(a,b)=1 使得和最大. [思路] 二分图的最大权独立集(可以这么叫么QAQ 先拆点,对于不满足条件的两个 ...
- bzoj3275
容易想到是最小割(最大权独立集)然后每个数拆成两个点,不能同时选的之间连边跑最小割,最后答案=总数-mincut/2 因为这样建图将流量变成了原来的两倍 当然这道题更好的建图方法是分成奇数和偶数两个集 ...
随机推荐
- Solution -「洛谷 P4372」Out of Sorts P
\(\mathcal{Description}\) OurOJ & 洛谷 P4372(几乎一致) 设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...
- 编译安装 tree 命令
文章目录 下载源码包 编译源码包 tree下载地址:http://mama.indstate.edu/users/ice/tree/ Centos发行版,可以直接使用命令 yum -y install ...
- Java并发基础之AbstractQueuedSynchronizer(AQS)
AbstractQueuedSynchronizer同步器是实现JUC核心基础组件,因为 定义了一套多线程访问共享资源的同步器框架.前面几篇文章中JUC同步工具中都利用AQS构建自身的阻塞类.AQS解 ...
- json系列(二)cjson,rapidjson,yyjson大整数解析精度对比
前言上一篇介绍了3种json解析工具的使用方法,对于基础数据的解析没有任何问题.我们传输的json数据里有unsigned long型数据,需要借助json解析工具得到正确的unsigned long ...
- 【C#操作符】typeof 和 is 运算符执行的类型检查之间的差异
typeof 运算符也能用于公开的泛型类型.具有不止一个类型参数的类型的规范中必须有适当数量的逗号.不能重载 typeof 运算符. is 可以检测和父类是否兼容,typeof责不能 public c ...
- 【Oracle】PLSQL如何更新、提交数据库中数据
转至:https://blog.csdn.net/Bee_AI/article/details/89279612 Oracle更新单表数据时,一般使用SELECT--FOR UPDATE语句,这条语句 ...
- 面向对象编程(C++篇1)——引言
目录 1. 概述 2. 详论 2.1. 类与对象 2.2. 数据类型 3. 目录 1. 概述 现代C++与最原始的版本已经差不多是两种不同的语言了.不断发展的C++标准给C++这门语言带来了更多的范式 ...
- LeetCode-001-两数之和
两数之和 题目描述:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标. 你可以假设每种输入只会对应一个答 ...
- 清华大学ucore操作系统课笔记
操作系统 清华大学ucore操作系统课笔记 全文思维导图 1. 操作系统概述 1.1 什么是操作系统? 操作系统的定义 没有公认的精确定义 一个控制程序 一个系统软件 控制程序执行过程,防止错误和计算 ...
- GateWay配置使用
是什么 Cloud全家桶中有个很重要的组建就是网关,在1.x版本中都是采用的Zuul网关 但在2.X版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关替代Zuul Sprin ...