最小路径覆盖问题是:给定一个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. docker制作镜像步骤

    一.查看宿主机下是否有符合需求的docker镜像 操作命令如下: [root@server4 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZ ...

  2. 利用rundll32执行程序的函数执行程序

    1.前言 无意间发现hexacorn这个国外大佬,给出了很多通过rundll32执行DLL中的函数执行程序的方法,思路很灵巧. 2.原理 rundll32加载dll 用法: rundll32 < ...

  3. Nginx/LVS/HAProxy负载均衡软件的优缺点详解【转】

    转自 (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解http://www.ha97.com/5646.html PS:Nginx/LVS/HAProxy是目前使用最广泛的三种负载均 ...

  4. 数据库——mysql如何获取当前时间

    1.1 获得当前日期+时间(date + time)函数:now() 除了 now() 函数能获得当前的日期时间外,MySQL 中还有下面的函数: current_timestamp() curren ...

  5. 洛谷P1342请柬

    传送门啦 核心思想:两遍最短路. 1号点去各地的时间直接套最短路模板,各地到1号点时间用逆向思维,视为求1号点沿反边到各地的时间即可. #include <iostream> #inclu ...

  6. oralce 笔记

    查某一表的行数 select max(rownum) from tablename 插入数据之前判断是否重复 insert into tablename (coloum1,coloum2) selec ...

  7. GreenPlum学习笔记:create or replace function创建函数

    原始表数据如下: 需求:现要求按分号“;”将rate_item列进行分割后插入到新的数据表中. CREATE OR REPLACE FUNCTION fun_gp_test_xxx_20181026( ...

  8. 20165203《Java程序设计》第九周学习总结

    20165203<Java程序设计>第九周学习总结 教材学习内容总结 URL类 URL类是java.net包中的一个重要的类,URL的实例封装着一个统一资源定位符,使用URL创建对象的应用 ...

  9. 20165203 实验三 敏捷开发与XP实践

    20165203 实验三 敏捷开发与XP实践 任务一: 1.实验要求 实验三 敏捷开发与XP实践 (http://www.cnblogs.com/rocedu/p/4795776.html), Ecl ...

  10. C#基础系列 - 抽象类及其方法的学习

    在C#中使用关键字 abstract 来定义抽象类和抽象方法. 不能初始化的类被叫做抽象类,它们只提供部分实现,但是另一个类可以继承它并且能创建它们的实例. "一个包含一个或多个纯虚函数的类 ...