最小路径覆盖问题是:给定一个DAG,该DAG的一个路径覆盖是一个路径的集合,使得每个点属于且仅属于其中一条路径,问题就是求一个大小最小的路径集合。

做法是将每个点A拆成两个点A1,A2,如果A->B,那么连A1->B2求一个最大匹配。

一个结论是:最小路径数 = 点数 - 最大匹配

证明的大概思路是:

  一个路径覆盖与一个边独立集(即一个匹配)一一对应。

  一个路径覆盖的路径数 = 点数 - 匹配数 ( 因为 路径数+每条路径的边数和-1 = n个点的无向联通无环图的边数 , 匹配数等于每条路径的边数和 )

 /**************************************************************
Problem: 2150
User: idy002
Language: C++
Result: Accepted
Time:52 ms
Memory:1652 kb
****************************************************************/ #include <cstdio>
#include <cstring>
#include <vector>
#define N 55
#define S N*N*2
#define oo 0x3f3f3f3f
using namespace std; struct Edge {
int u, v, f;
Edge( int u, int v, int f ):u(u),v(v),f(f){}
}; int n, m, r, c, cnt;
char board[N][N];
int idx[][N][N], src, dst, idc;
int dx[], dy[]; vector<Edge> edge;
vector<int> g[S];
int dep[S], cur[S], qu[S], bg, ed; void makeid() {
idc = ;
src = ++idc;
for( int i=; i<=n; i++ )
for( int j=; j<=m; j++ )
for( int c=; c<; c++ )
idx[c][i][j] = ++idc;
dst = ++idc;
}
void adde( int u, int v, int f ) {
g[u].push_back( edge.size() );
edge.push_back( Edge(u,v,f) );
g[v].push_back( edge.size() );
edge.push_back( Edge(v,u,) );
}
void build() {
for( int i=; i<=n; i++ )
for( int j=; j<=m; j++ ) {
if( board[i][j]!='.' ) continue;
adde( src, idx[][i][j], );
adde( idx[][i][j], dst, );
}
for( int i=; i<=n; i++ )
for( int j=; j<=m; j++ ) {
if( board[i][j]!='.' ) continue;
int u = idx[][i][j];
for( int d=; d<; d++ ) {
int ni = i+dx[d];
int nj = j+dy[d];
if( <=ni&&ni<=n && <=nj&&nj<=m && board[i][j]=='.' ) {
int v = idx[][ni][nj];
adde( u, v, );
}
}
}
}
bool bfs() {
memset( dep, , sizeof(dep) );
qu[bg=ed=] = src;
dep[src] = ;
while( bg<=ed ) {
int u=qu[bg++];
for( int t=; t<g[u].size(); t++ ) {
Edge &e = edge[g[u][t]];
if( e.f && !dep[e.v] ) {
dep[e.v] = dep[e.u]+;
qu[++ed] = e.v;
}
}
}
return dep[dst];
}
int dfs( int u, int a ) {
if( u==dst || a== ) return a;
int remain=a, past=, na;
for( int &t=cur[u]; t<g[u].size(); t++ ) {
Edge &e=edge[g[u][t]];
Edge &ve=edge[g[u][t]^];
if( e.f && dep[e.v]==dep[e.u]+ && (na=dfs(e.v,min(remain,e.f))) ) {
remain -= na;
past += na;
e.f -= na;
ve.f += na;
if( !remain ) break;
}
}
return past;
}
int maxflow() {
int flow = ;
while( bfs() ) {
memset( cur, , sizeof(cur) );
flow += dfs(src,oo);
}
return flow;
}
int main() {
scanf( "%d%d%d%d", &n, &m, &r, &c );
dx[]=r, dy[]=c, dx[]=r, dy[]=-c;
dx[]=c, dy[]=r, dx[]=c, dy[]=-r;
for( int i=; i<=n; i++ ) {
scanf( "%s", board[i]+ );
for( int j=; board[i][j]; j++ )
if( board[i][j]=='.' ) cnt++;
}
makeid();
build();
printf( "%d\n", cnt-maxflow() );
}

bzoj 2150 最小路径覆盖的更多相关文章

  1. BZOJ.1927.[SDOI2010]星际竞速(无源汇上下界费用流SPFA /最小路径覆盖)

    题目链接 上下界费用流: /* 每个点i恰好(最少+最多)经过一次->拆点(最多)+限制流量下界(i,i',[1,1],0)(最少) 然后无源汇可行流 不需要源汇. 注: SS只会连i',求SS ...

  2. bzoj 2044 三维导弹拦截——DAG最小路径覆盖(二分图)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2044 还以为是CDQ.发现自己不会三维以上的…… 第一问可以n^2.然后是求最长不下降子序列 ...

  3. bzoj 2044 三维导弹拦截 —— 最小路径覆盖

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2044 第一问暴力 n^2 即可: 注意这道题对位置没要求!所以先按第一维排序一下即可: 然后 ...

  4. BZOJ-2150部落战争(最小路径覆盖)

    2150: 部落战争 Time Limit: 10 Sec  Memory Limit: 259 MB Description lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国 ...

  5. 【HDU1960】Taxi Cab Scheme(最小路径覆盖)

    Taxi Cab Scheme Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  6. loj 1429(可相交的最小路径覆盖)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1429 思路:这道题还是比较麻烦的,对于求有向图的可相交的最小路径覆盖,首先要解决成环问 ...

  7. 【HDU3861 强连通分量缩点+二分图最小路径覆盖】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 题目大意:一个有向图,让你按规则划分区域,要求划分的区域数最少. 规则如下:1.有边u到v以及有 ...

  8. POJ 3216 最小路径覆盖+floyd

    Repairing Company Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 6646   Accepted: 178 ...

  9. POJ3020Antenna Placement(最小路径覆盖+重在构图)

    Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7788   Accepted: 3880 ...

随机推荐

  1. rollup&&cube

    group by 擴展 rollup&&cube --按job分組計算不同job的匯總工資   SELECT job, SUM (sal)     FROM emp GROUP BY ...

  2. python基础之命名空间

    前言 命名空间通俗的理解就是对象或变量的作用范围,在python中分为局部命令空间.模块命名空间和build-in全局命名空间. 局部命名空间 局部命名空间即在一个函数或一个类中起作用的变量或引用的字 ...

  3. RW RO ZI ROM keil中的含义

    编译的一个ARM的程序,会得到这样的信息: ============================================================================== ...

  4. overridePendingTransition()使用

    实现两个 Activity 切换时的动画.在Activity中使用有两个参数:进入动画和出去的动画. 注意1.必须在 StartActivity()  或 finish() 之后立即调用.2.而且在 ...

  5. TF-搞不懂的TF矩阵加法

    看谷歌的demo mnist,卷积后加偏执量的代码 h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)h_pool1 = max_pool ...

  6. 利用vw+rem实现移动web适配布局

    基本概念 1.单位 Px(CSS pixels) 像素 (px) 是一种绝对单位(absolute units), 因为无论其他相关的设置怎么变化,像素指定的值是不会变化的 其实是相对于某个设备而言的 ...

  7. 《精通Python设计模式》学习结构型之适配器模式

    大名鼎鼎~~ 在兼容老系统和其它系统外调用时,用得着~ class Synthesizer: def __init__(self, name): self.name = name def __str_ ...

  8. android拾遗——AlarmManager的使用

    AlarmManager的作用文档中的解释是:在特定的时刻为我们广播一个指定的Intent.简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定的Inten ...

  9. CCF CSP 201409-3 字符串匹配

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201409-3 字符串匹配 问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那 ...

  10. CentOS7.5安装MongoDB4.0与CRUD基本操作

    一 MongoDB简介 MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介于关系数据库和非关系数 ...