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

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

先构造二分图: 对于原图,先拆点,吧每个点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];
}
else
if(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;
}

有向图最小路径覆盖方法浅析、证明 //hdu 3861的更多相关文章

  1. HDOJ1151有向图最小路径覆盖

    //有向图最小路径覆盖:从某一点出发沿着有向路径,不走回路,能将所有的结点遍历. #include<iostream> #include<cstdio> #include< ...

  2. (匹配 最小路径覆盖)Air Raid --hdu --1151

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1151 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  3. ●hihocoder #1394 网络流四·最小路径覆盖

    题链: http://hihocoder.com/problemset/problem/1394 题解: 有向图最小路径覆盖:最少的路径条数不重不漏的覆盖所有点. 注意到在任意一个最小路径覆盖的方案下 ...

  4. HDU 3861 The King’s Problem 最小路径覆盖(强连通分量缩点+二分图最大匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 最小路径覆盖的一篇博客:https://blog.csdn.net/qq_39627843/ar ...

  5. hdu 1151 Air Raid(二分图最小路径覆盖)

    http://acm.hdu.edu.cn/showproblem.php?pid=1151 Air Raid Time Limit: 1000MS   Memory Limit: 10000K To ...

  6. (step6.3.4)hdu 1151(Air Raid——最小路径覆盖)

    题意:     一个镇里所有的路都是单向路且不会组成回路. 派一些伞兵去那个镇里,要到达所有的路口,有一些或者没有伞兵可以不去那些路口,只要其他人能完成这个任务.每个在一个路口着陆了的伞兵可以沿着街去 ...

  7. HDU 3861 The King’s Problem(tarjan连通图与二分图最小路径覆盖)

    题意:给我们一个图,问我们最少能把这个图分成几部分,使得每部分内的任意两点都能至少保证单向连通. 思路:使用tarjan算法求强连通分量然后进行缩点,形成一个新图,易知新图中的每个点内部的内部点都能保 ...

  8. HDU 3861.The King’s Problem 强联通分量+最小路径覆盖

    The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  9. HDU 3861 The King’s Problem(强连通+二分图最小路径覆盖)

    HDU 3861 The King's Problem 题目链接 题意:给定一个有向图,求最少划分成几个部分满足以下条件 互相可达的点必须分到一个集合 一个对点(u, v)必须至少有u可达v或者v可达 ...

随机推荐

  1. python:lambda、filter、map、reduce

    lambda 为关键字.filter,map,reduce为内置函数. lambda:实现python中单行最小函数. g = lambda x: x * 2 #相当于 def g(x): retur ...

  2. 快学UiAutomator配置编辑环境

    Java环境配置 1.下载jdk1.6+包 2.安装jdk,默认安装即可 3.成功安装之后,进行测试是否真的成功安装,点击[开始]----[运行]----输入 CMD,在命令提示符里面输入“Java ...

  3. java script DOM BOM

    onclick        当用户点击某个对象时调用的事件句柄.ondblclick     当用户双击某个对象时调用的事件句柄. onfocus        元素获得焦点.            ...

  4. js的工厂模式

    工厂模式: 什么叫工厂模式,工厂就是大家大脑里想的那样,一个流水线作业的一个东西,只需要满足刚需就可以了,一个人,只干一件事,最后串起来,就是一个事件. 首先需要说一下工厂模式.工厂模式根据抽象程度的 ...

  5. 带图形桌面的CentOS7----中安装VMWareTools以及支持中文输入

    主机是WIN10操作系统 安装VMWareTools的方法:https://jingyan.baidu.com/article/e8cdb32b136ad637052bad26.html 在图形化Ce ...

  6. (48)zabbix报警媒介:自定义脚本Custom alertscripts

    自定义脚本媒介.zabbix会将信息传递给脚本,接下来你在脚本里面随意处理,一共会传递三个参数,按顺序接受也就是$1,$2,$3了,为了方便记忆,一般分别给他们赋值到To\Subject\body 配 ...

  7. UNIX环境C语言进程通信

    一.信号管理 1.函数signal signal函数是UNIX系统信号机制最简单的接口 #include <signal.h> typedef void (*sighandler_t)(i ...

  8. CSS3-::selection

    “::selection”只能设置两个属性,一个就是background,另一个就是color属性,设置其他属性是没有任何效果的. ::selection使用语法: /*Webkit,Opera9.5 ...

  9. Python中变量的命名与使用(个人总结)

    与众多编程语言一样,Python变量的命名有一定的规范: 变量名只能包含字母.数字.下划线且不能以数字开头.例如,num_1 为正确命名,而 1_num 则错误. 变量名不允许含空格,但是可以用下划线 ...

  10. 快照、克隆,xshell优化,Linux历史

    目录 一.虚拟拍照功能 二.虚拟机克隆功能 三.Xshell的优化 四.介绍Linux历史 一.虚拟拍照功能 1.拍摄快照 关机状态拍照 关机命令:shutdown -h now 或者 init 0 ...