当前位置: 首页 > news >正文

有向无环图(DAG)的最小路径覆盖

转自https://www.cnblogs.com/justPassBy/p/5369930.html

DAG的最小路径覆盖

定义:在一个有向图中,找出最少的路径,使得这些路径经过了所有的点。

最小路径覆盖分为最小不相交路径覆盖最小可相交路径覆盖

最小不相交路径覆盖:每一条路径经过的顶点各不相同。如图,其最小路径覆盖数为3。即1->3>4,2,5。

最小可相交路径覆盖:每一条路径经过的顶点可以相同。如果其最小路径覆盖数为2。即1->3->4,2->3>5。

特别的,每个点自己也可以称为是路径覆盖,只不过路径的长度是0。

 

DAG的最小不相交路径覆盖

算法:把原图的每个点V拆成VxVx和VyVy两个点,如果有一条有向边A->B,那么就加边Ax>ByAx−>By。这样就得到了一个二分图。那么最小路径覆盖=原图的结点数-新图的最大匹配数。

证明:一开始每个点都是独立的为一条路径,总共有n条不相交路径。我们每次在二分图里找一条匹配边就相当于把两条路径合成了一条路径,也就相当于路径数减少了1。所以找到了几条匹配边,路径数就减少了多少。所以有最小路径覆盖=原图的结点数-新图的最大匹配数。

因为路径之间不能有公共点,所以加的边之间也不能有公共点,这就是匹配的定义。

习题:POJ1422

//
//  main.cpp
//  POJ1422最小不想交路径覆盖
//
//  Created by beMaster on 16/4/8.
//  Copyright © 2016年 beMaster. All rights reserved.
//

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
const int N = 200 + 10;
vector<int> g[N];
int cy[N];
bool vis[N];
bool dfs(int u){
    for(int i=0; i<g[u].size(); ++i){
        int v = g[u][i];
        if(vis[v]) continue;
        vis[v] = true;
        if(cy[v]==-1 || dfs(cy[v])){
            cy[v] = u;
            return true;
        }
    }
    return false;
}
int solve(int n){
    int ret = 0;
    memset(cy, -1, sizeof(cy));
    for(int i=1;i<=n;++i){
        memset(vis, 0, sizeof(vis));
        ret += dfs(i);
    }
    return n - ret;
}
int main(int argc, const char * argv[]) {
    int t,n,m;
    int u,v;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
            g[i].clear();
        for(int i=0;i<m;++i){
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
        }
        
        int ans = solve(n);
        printf("%d\n",ans);
    }
    return 0;
}

  

DAG的最小可相交路径覆盖

算法:先用floyd求出原图的传递闭包,即如果a到b有路径,那么就加边a->b。然后就转化成了最小不相交路径覆盖问题。

证明:为了连通两个点,某条路径可能经过其它路径的中间点。比如1->3->4,2->4->5。但是如果两个点a和b是连通的,只不过中间需要经过其它的点,那么可以在这两个点之间加边,那么a就可以直达b,不必经过中点的,那么就转化成了最小不相交路径覆盖。

题目:POJ2594

//
//  main.cpp
//  POJ2594最小可相交路径覆盖
//
//  Created by beMaster on 16/4/8.
//  Copyright © 2016年 beMaster. All rights reserved.
//

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
const int N = 500 + 10;
bool dis[N][N];
bool vis[N];
int cy[N];
void floyd(int n){
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            for(int k=1;k<=n;++k)
                if(dis[i][k] && dis[k][j])//传递可达性
                    dis[i][j] = true;
}
bool dfs(int u, int n){
    for(int i=1;i<=n;++i){
        if(!vis[i] && dis[u][i]){
            vis[i] = true;
            if(cy[i]==-1 || dfs(cy[i], n)){
                cy[i] = u;
                return true;
            }
        }
    }
    return false;
}
int solve(int n){
    int cnt = 0;
    memset(cy,-1,sizeof(cy));
    for(int i=1;i<=n;++i){
        memset(vis,0,sizeof(vis));
        cnt += dfs(i, n);
    }
    return n - cnt;
}
int main(int argc, const char * argv[]) {
    int n,m;
    int a,b;
    while(scanf("%d%d",&n,&m),n+m){
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
                dis[i][j] = false;
        for(int i=1;i<=m;++i){
            scanf("%d%d",&a,&b);
            dis[a][b] = true;
        }
        floyd(n);
        int ans = solve(n);
        printf("%d\n",ans);
    }
    return 0;
}

  

转载于:https://www.cnblogs.com/mybing/p/9047962.html

相关文章:

  • winSCP:无权访问
  • VS Code 折腾记 - (13) VS Live Share (可提高效率的代码实时协作插件)的使用姿势
  • 百度Api完成在线地图定位显示
  • windows堆栈研究以及线程安全
  • 给nginx生成自签名证书
  • Python之合并PDF文件
  • git 常用命令说明
  • CSS3学习之background-origin和background-clip区别
  • Kuberbetes1.10 集群部署
  • Linux常用基本命令:uniq-去重复
  • ijkplayer视频播放
  • ⽹站部署到阿里服务器及域名配置流程
  • stun服务器搭建(coTurn)
  • 讲清楚之javascript作用域
  • Windows Containers 大冒险: 容器网络
  • 【技术性】Search知识
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • conda常用的命令
  • If…else
  • Java新版本的开发已正式进入轨道,版本号18.3
  • mysql innodb 索引使用指南
  • Vue 重置组件到初始状态
  • WinRAR存在严重的安全漏洞影响5亿用户
  • 测试如何在敏捷团队中工作?
  • 从零开始的无人驾驶 1
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 聊聊sentinel的DegradeSlot
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 限制Java线程池运行线程以及等待线程数量的策略
  • ​软考-高级-系统架构设计师教程(清华第2版)【第20章 系统架构设计师论文写作要点(P717~728)-思维导图】​
  • (¥1011)-(一千零一拾一元整)输出
  • (23)Linux的软硬连接
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (强烈推荐)移动端音视频从零到上手(下)
  • (十)c52学习之旅-定时器实验
  • (四) Graphivz 颜色选择
  • (推荐)叮当——中文语音对话机器人
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET 回调、接口回调、 委托
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .net和jar包windows服务部署
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • .net连接oracle数据库
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • @EnableConfigurationProperties注解使用
  • @Resource和@Autowired的区别
  • @TableId注解详细介绍 mybaits 实体类主键注解
  • @德人合科技——天锐绿盾 | 图纸加密软件有哪些功能呢?
  • [ IOS ] iOS-控制器View的创建和生命周期
  • [acwing周赛复盘] 第 94 场周赛20230311