路径覆盖就是在图中找一些路径,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联。

对于一个有向无环图怎么求最小路径覆盖?

先构造二分图: 对于原图,先拆点,吧每个点i拆成ii,iii。若有边i--》j,则在二分图中,添加边 ii--》jjj(即原来每个点拆为一个入点和出点),这样构成二分图。

则:最小路径覆盖数=原图顶点数-二分图最大匹配数。

粗略解析证明:(设有n个顶点)

若原图没有边,则最大匹配数为0,最小路径覆盖为n,思想:每得到一个匹配,相当于把这俩个点并为一个集合(原来有N个集合),即这俩个点在原图中是在同一条路径覆盖上的,每次成功匹配,相当于一次成功“并集”,所谓的路径覆盖,可以理解为合并顶点的动作,而匹配的点不重复(分出俩个点恰好对应路径覆盖时该店的一出一入),每成功一次匹配,则顶点集合少了一,即路径少了一条,所以最小路径覆盖对应最大匹配的时候,即证。

该题(hdu3861),题意:划分一个有向图,要求:1,:同一个强连通分量(SCC)中的点属于一个集合,2:每个点只属于一个集合。3:任意俩个点都可以单向抵达的(不能越过其他集合)是属于一个集合。

原图不是无环图,先缩点,成有向无环图,在求最下路径覆盖,按上面方法,代码有注解:

(转载请注明出处。)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
int n,m;
const int MAX=50010*2;const int inf=0x3f3f3f3f;
vector<vector<int> >v(MAX);
int vis[MAX];int dfn[MAX];int low[MAX];
int times=0;int scc[MAX];int ins[MAX];stack<int>s;
int num=0;             //缩点后点数
int e[MAX*3][3];int head[MAX*2];int nume=0;
void clea()    //初始化工作
{for(int i=0;i<=2*n+1;i++){head[i]=-1;ins[i]=dfn[i]=vis[i]=low[i]=scc[i]=0;v[i].clear();}num=0;times=0;nume=0;
}
void inline adde(int f,int s,int w) //添加新图(二分图)的边,用网络流法解,所用之
{e[nume][0]=s;e[nume][1]=head[f];head[f]=nume;e[nume++][2]=w;e[nume][0]=f;e[nume][1]=head[s];head[s]=nume;e[nume++][2]=0;
}
void tarjan(int u)  //有向图缩点
{dfn[u]=low[u]=++times;ins[u]=1;s.push(u);for(int i=0;i<v[u].size();i++){int ch=v[u][i];if(!vis[ch]){vis[ch]=1;tarjan(ch);if(low[ch]<low[u])low[u]=low[ch];}elseif(ins[ch]&&dfn[ch]<low[u])low[u]=dfn[ch];}if(low[u]==dfn[u]){int cur;num++;do{cur=s.top();s.pop();scc[cur]=num;ins[cur]=0;}while(cur!=u);}
}
void  get_newgraph() //获得新图,二分图
{for(int i=1;i<=n;i++){for(int j=0;j<v[i].size();j++){int c=v[i][j];if(scc[i]!=scc[c]){adde(scc[i],scc[c]+num,1);}}}for(int i=1;i<=num;i++){adde(0,i,1);adde(i+num,num+num+1,1);}
}
int lev[MAX];  //网络流法求最大匹配  添加源汇点(0,2*num+1),流量为1,有重边也不无纺。
bool bfs()
{for(int i=0;i<=num*2+1;i++){lev[i]=vis[i]=0;}queue<int>q;q.push(0);vis[0]=1;while(!q.empty()){int cur=q.front();q.pop();for(int i=head[cur];i!=-1;i=e[i][1]){int c=e[i][0];if(!vis[c]&&e[i][2]>0){lev[c]=lev[cur]+1;if(c==num*2+1)return 1;vis[c]=1;q.push(c);}}}return vis[num*2+1];
}
int dfs(int u,int minf)
{if(u==num*2+1||minf==0)return minf;int sum=0,f;for(int i=head[u];i!=-1&&minf;i=e[i][1]){int c=e[i][0];if(lev[c]==lev[u]+1&&e[i][2]>0){f=dfs(c,minf<e[i][2]?minf:e[i][2]);e[i][2]-=f;e[i^1][2]+=f;sum+=f;minf-=f;}}return sum;
}
int dinic()
{int sum=0;while(bfs()){sum+=dfs(0,inf);}return sum;
}
int main()
{int ta;scanf("%d",&ta);while(ta--){scanf("%d%d",&n,&m);int aa,bb;clea();for(int i=0;i<m;i++){scanf("%d%d",&aa,&bb);v[aa].push_back(bb);}for(int i=1;i<=n;i++){if(!vis[i]){vis[i]=1;tarjan(i);}}get_newgraph();int ans=num-dinic();  //最小路径覆盖数printf("%d\n",ans);}return 0;
}

转载于:https://www.cnblogs.com/yezekun/p/3925718.html

有向图最小路径覆盖方法浅析、证明 //hdu 3861相关推荐

  1. HDU - 1151 Air Raid(最小路径覆盖-二分图最大匹配)

    题目链接:点击查看 题目大意:给出一个有向图,现在需要在不同的地方空降伞兵,保证所有伞兵沿着道路可以走完所有城市,求出最少伞兵的数量 题目分析:我们的目的是要用最少的路径覆盖所有顶点,换句话说就是二分 ...

  2. HDU 3861 The King’s Problem (强连通缩点+DAG最小路径覆盖)

    <题目链接> 题目大意: 一个有向图,让你按规则划分区域,要求划分的区域数最少. 规则如下:1.所有点只能属于一块区域:2,如果两点相互可达,则这两点必然要属于同一区域:3,区域内任意两点 ...

  3. 最小路径覆盖与最小链覆盖 Dilworth定理:最小链覆盖等于最长反链(详细证明与经典例题)

    一.最小路径覆盖 定义 最小路径覆盖就是指在有向无环图中,用最少的.不相交的简单路径覆盖图中的所有点. 解法 ①将原图中的每个点拆点,(将点u拆成u与u+n): ②将原图中的每条边 <u,v&g ...

  4. hdu 4160 (Dolls)二分图的最小路径覆盖

    关于二分图,让人很头疼啊!归结为一句话,就是看不出来题目是二分图的问题. 也许是对二分图不太熟悉吧!需要多练习! 题目大意:给出n个箱子,每个箱子的参数为长,宽,高:(a,b,c):当且仅当箱子s1, ...

  5. HDU 3861 The King’s Problem 强连通分量 最小路径覆盖

    先找出强连通分量缩点,然后就是最小路径覆盖. 构造一个二分图,把每个点\(i\)拆成两个点\(X_i,Y_i\). 对于原图中的边\(u \to v\),在二分图添加一条边\(X_u \to Y_v\ ...

  6. (hdu step 6.3.3)Air Raid(最小路径覆盖:求用最少边把全部的顶点都覆盖)

    题目: Air Raid Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...

  7. 二分图专题系列各大知识点总结(匈牙利,染色法,最大独立集,最小点覆盖,最小路径覆盖)

    本文概论 二分图的判断方法:图中不存在奇数环----->染色法判断二分图不存在矛盾 二分图: 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i, ...

  8. 二分图大讲堂——彻底搞定最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配

    二分图匹配 二分图大讲堂--彻底搞定最大匹配数(最小覆盖数).最大独立数.最小路径覆盖.带权最优匹配(转) 文本内容框架: §1图论点.边集和二分图的相关概念和性质 §2二分图最大匹配求解 匈牙利算法 ...

  9. 最大匹配、最小顶点覆盖、最大独立集、最小路径覆盖(转)

    在讲述这两个算法之前,首先有几个概念需要明白: 二分图:  二分图又称二部图,是图论中的一种特殊模型.设G=(V,E)是一个无向图,如果顶点V可以分割为两个互不相交的子集(A,B),并且图中的每条边( ...

最新文章

  1. 极限编程 (Extreme Programming) 和用户故事 (User Stories) 的关系
  2. 三本毕业后,我进入了世界五百强
  3. Git GUI使用(二)
  4. 百步斋诗钞【绝句四首】
  5. 详解SQL Server连接(内连接、外连接、交叉连接)
  6. 哈工大计算机网络Week2-网络应用数据交换
  7. 安装 Flex2packagebeta_1.994
  8. 链接oracle spatial,oracle spatial初试
  9. LeetCode Gray Code 格雷码
  10. oc知识点 类的扩展
  11. php 点击文本框弹出时间,点击Input框弹出日期选项
  12. 关于webservice(CXF)的一些理解
  13. 【Elasticsearch】es查看有问题的索引或者分片
  14. 《大话数据结构》读后总结(八)
  15. mysql 打印_揭秘MySQL 主从环境中大事务的传奇事迹
  16. Microsoft Visio 画图遇到的问题及解决办法
  17. 三校生高考计算机专业试题,三校生高考计算机试卷1
  18. 关于自抗扰控制的一些中文论文
  19. DiskGenius 对 U 盘分区操作后保存更改时报错:保存分区表时出现错误20000011e no such partition
  20. swagger主页访问,返回报错500

热门文章

  1. 5 门可能衰落的编程语言
  2. TensorFlow被曝存在严重bug,搭配Keras可能丢失权重,用户反映一个月仍未修复
  3. 600页!分享珍藏很久的《推荐系统学习手册》(附下载链接及入门经验)
  4. 初学Python,我给你总结了常见的17个错误
  5. Redis的rdb格式学习
  6. 跳跃游戏(判断是否可以跳到最后一个下标)
  7. 文档相似度之doc2vec、文档聚类
  8. 复习计算机网络基础 day9--应用层
  9. 使用Python分析姿态估计数据集COCO的教程
  10. 基于OpenCV的行人目标检测