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 因为这样建图将流量变成了原来的两倍 当然这道题更好的建图方法是分成奇数和偶数两个集 ...
随机推荐
- TCP/IP详解 读书笔记:TCP:传输控制协议
TCP的服务 TCP为应用层提供一种面向连接的.可靠的字节流服务. 一个TCP连接中,仅有两方进行彼此通信,所以广播和多播不能用于TCP. TCP通过以下方式提供可靠性: 应用数据被切割为TCP认为最 ...
- MyBatis缓存Cache包
Mybatis默认使用了一级缓存为数据查询提供效率,其底层数据结构为PerpetualCache.同时MyBatis不止实现了PerpetualCache,还有其他实现提供其他功能,如下: 可以从UM ...
- [自动化]基于kolla-ansible部署的openstack自动化巡检生成xlsx报告
自动化巡检介绍 此巡检项目在kolla-ansible部署的openstack环境上开发,利用ansible-playbook编排的功能,对巡检的任务进行编排和数据处理.主要巡检的对象有IaaS平台和 ...
- python的字符串切片技术
听说过python的字符串切片技术吗?是不是听着超高级的?实际上,也不用想得太难,python的字符串切片技术就是将字符串的某些字符提取出来而已~ 字符串切片 字符串是一种序列类型,可以按序号访问其中 ...
- python中的list, dict, tuple以及collections模块的基本用法
1.关于list的一些基本用法 # 创建没有初值的列表 list1=[] # 创建有初值的列表 list2=['this','is','a','list'] # 创建给定长度但初值不确定的列表 lis ...
- Hive常用函数大全-字符串函数
1.字符串长度函数:length(X)(返回字符串X的长度) select length('qwerty') from table --6 2.字符串反转函数:reverse(X)(返回字符串X反转的 ...
- Python常用内建模块和第三方库
目录 内建模块 1 datetime模块(处理日期和时间的标准库) datetime与timestamp转换 str与datetime转换 datetime时间加减,使用timedelta这个类 转 ...
- docker:alpine使用logrotate切割日志
最近在交付项目的时候使用了docker,大家都知道日志是项目定位问题的重要依据,但如果一开始项目本身没有对日志进行合理切割那就会导致长时间运行的项目日志文件大得编辑器打不开的情况.这里使用大部分lin ...
- C++ 部分函数
string库 1.size()与length() 字符串长,结果相同 string s; s.length(); //s.length()-1是最后一个字符的下标,而不是'\0' for(i=0;i ...
- (转载)C 中static 和inline
https://www.cnblogs.com/lxlx1798/articles/9996521.html