LA 3126 二分匹配---DAG中的最小路径应用

题意:有 n 个顾客 , 需要坐出租车从一个地方去另一个地方 , 每个顾客的出发时间、出发地点、目的地点都已给出 , 从出发地点到目的地点的时间为两地之间的路径长度 , 并且出租车要比顾客的出发时间早一分钟到达 , 问最少需要派出多少辆出租车。

解法:我们先这样来构图 , 每个顾客是一个结点,如果同一个出租车在接完客人 u 之后还来得及节客人 v , 那么就在 u 到 v 之间连一条有向边 。 由此可以发现 , 这个图是一个DAG , 那么我们就只需要找最小路径覆盖(最小路径覆盖:是指在图中找尽量少的路径,去覆盖每一个点,并且每个路径之间没有公共点)。

对于最小路径覆盖,我们先进行拆点  , 把图边为一个二分图 , 把所有结点 拆为两个结点 , 如 结点 u 拆为 u1 , u2 , 如果 u 到 v 有一条有向边 , 那么我们就连接 u1 到 v2 的一条边。

这时我们只需要求出这个图的最大匹配 , 结果就是: n - m(最大匹配数)。

为什么?

因为匹配和路径覆盖是一一对应的 , 对于路径覆盖中的每条简单路径 , 除了最后一个“结尾结点”之外,都有唯一的后继与其对应(也就是匹配结点) , 因此匹配数就是非“结尾结点”的个数 , 但匹配数达到最大时 , 也就是“结尾结点”最小 , 也就是路径最小。

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <cmath>

using namespace std;

#define maxn 520

vector<int>grap[maxn];
int cab[maxn][4] , cab_t[maxn][2];
int n;
int pre[maxn] , cx[maxn] , cy[maxn];

void init()
{
    for(int i = 0; i < n; i++)
        grap[i].clear();
    memset(cx , -1 , sizeof(cx));
    memset(cy , -1 , sizeof(cy));
}

void create_grap()
{
    int i , j;
    int x , y;
    int h , m;
    for(i = 0; i < n; i++)
    {
        y = abs(cab[i][0]-cab[i][2])+abs(cab[i][1]-cab[i][3]);
        for(j = 0; j < n; j++)
        {
            if(i == j)  continue;
            x = y+abs(cab[j][0]-cab[i][2])+abs(cab[j][1]-cab[i][3]);
            m = (x+cab_t[i][1])%60;
            h = cab_t[i][0]+(x+cab_t[i][1])/60;
            if(h < cab_t[j][0] || (h == cab_t[j][0]&&m < cab_t[j][1]))
                grap[i].push_back(j);
        }
    }
}

int findpath(int u)
{
    int i , v;
    for(i = 0; i < grap[u].size(); i++)
    {
        v = grap[u][i];
        if(!pre[v])
        {
            pre[v] = 1;
            if(cy[v] == -1 || findpath(cy[v]))
            {
                cy[v] = u;
                cx[u] = v;
                return 1;
            }
        }
    }
    return 0;
}

int match()
{
    int i , cas = 0;
    for(i = 0; i < n; i++)
        if(cx[i] == -1)
        {
            memset(pre , 0 , sizeof(pre));
            cas += findpath(i);
        }

    return cas;
}

int main()
{
    int t;
    scanf("%d" , &t);
    while(t--)
    {
        scanf("%d" , &n);
        init();

        int i ;
        for(i = 0; i < n; i++)
            scanf("%d:%d %d %d %d %d" , &cab_t[i][0] , &cab_t[i][1] , &cab[i][0] , &cab[i][1] , &cab[i][2] , &cab[i][3]);
        create_grap();

        int cas = match();
        cout<<n-cas<<endl;
    }
    return 0;
}

LA 3126 二分匹配---DAG中的最小路径应用

时间: 2024-08-28 15:40:26

LA 3126 二分匹配---DAG中的最小路径应用的相关文章

POJ 1442 Air Raid(DAG图的最小路径覆盖)

题意: 有一个城镇,它的所有街道都是单行(即有向)的,并且每条街道都是和两个路口相连.同时已知街道不会形成回路. 可以在任意一个路口放置一个伞兵,这个伞兵会顺着街道走,依次经过若干个路口. 问最少需要投放几个伞兵,使得每个路口都被伞兵拜访过.并且要满足每个路口只能被一个伞兵拜访过. 思路: 裸DAG图的最小路径覆盖. DAG图的最小路径覆盖数 = 节点数 - 二分图最大匹配 代码: vector<int> graph[125]; int cx[125],cy[125]; bool bmask[

poj 2060 Taxi Cab Scheme(DAG图的最小路径覆盖)

题意: 出租车公司有M个订单. 订单格式:     hh:mm  a  b  c  d 含义:在hh:mm这个时刻客人将从(a,b)这个位置出发,他(她)要去(c,d)这个位置. 规定1:从(a,b)到(c,d)所花的时间为:abs(a-c)+abs(b-d). 规定2:一辆出租车如果要接单,必须在客人出发前1分钟(包括)以前接单. 问,最少派出多少辆出租车,可以完成所有任务. 思路: 把每一笔单看成一个点,如果完成第i个单后可以接到第j个单,则 i->j连上线. 则题为:求这个DAG图的最小路

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

DAG的最小路径覆盖 定义:在一个有向图中,找出最少的路径,使得这些路径经过了所有的点. 最小路径覆盖分为最小不相交路径覆盖和最小可相交路径覆盖. 最小不相交路径覆盖:每一条路径经过的顶点各不相同.如图,其最小路径覆盖数为3.即1->3>4,2,5. 最小可相交路径覆盖:每一条路径经过的顶点可以相同.如果其最小路径覆盖数为2.即1->3->4,2->3>5. 特别的,每个点自己也可以称为是路径覆盖,只不过路径的长度是0. DAG的最小不相交路径覆盖 算法:把原图的每个点

矩阵中的最小路径

package 数阵中的最优路径; import java.util.Scanner; public class Main2 { /** * 数阵中的最小路径搜索 * 1:设计要点 * 应用动态规划设计从右下角逐行至左上角,确定n,m后,随机产生的整数二维数组a(n,m)作矩阵输出同时赋值给部分和数组b(n,m). * 数组b(i,j)为点(i,j)到到右下角的最小数值和stm(i,j)是点(i,j)向右(R)或向下(D)或向右下(0)的路标数组 * 注意到最后一行与最后一列各数只有一个出口,于

hdu1151 Air Raid,DAG图的最小路径覆盖

点击打开链接 有向无环图的最小路径覆盖 = 顶点数- 最大匹配 #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 150; int g[maxn][maxn]; int n, m; int link[maxn]; bool used[

Machine Schedule 赤裸裸的二分匹配 二部图中的点覆盖书==匹配数

Machine Schedule 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #i

C#正则表达式匹配HTML中的图片路径

最近的项目中有个关于网页取图的功能需要我自己开发,那就是用正则表达式来匹配图片标签. 一般来说一个 HTML 文档有很多标签,比如“<html>”.“<body>”.“<table>”等,想把文档中的 img 标签提取出来并不是一件容易的事.由于 img 标签样式变化多端,使提取的时候用程序寻找并不容易.于是想要寻找它们就必须写一个非常健全的正则表达式,不然有可能会找得不全,或者找出来的不是正确的 img 标签. 我们可以从 HTML 标签的格式去想应该怎么建这个正则表

php匹配页面中的所有路径

方法一 $url='http://www.google.cn/search?q=php'; $html=file_get_contents($url); $dom = new DOMDocument(); @$dom->loadHTML($html); $xpath = new DOMXPath($dom); $hrefs = $xpath->evaluate("/html/body//a"); for ($i = 0; $i < $hrefs->length;

hdu1151 poj1422 最小路径覆盖.最大二分匹配

Air RaidTime Limit:1000MS    Memory Limit:10000KB    64bit IO Format:%I64d & %I64u SubmitStatusPracticePOJ 1422 Appoint description: Description Consider a town where all the streets are one-way and each street leads from one intersection to another.