UVA-1201 - Taxi Cab Scheme(POJ-2060)--DAG的最小路径覆盖

刘汝佳新书--训练指南

本题中时间是一个天然的序,因此可以构图如下:每个客人是一个点,如果同一个出租车在接完客人u以后来得及接客人v,连边u->v。不难发现这个图是一个DAG,并且它的最小路径覆盖就是本题的答案。

最小路径覆盖=结点数-最大匹配数

证明:

DAG最小路径覆盖的解法如下:把所有结点i拆成X结点i和Y结点i',如果图G中存在有向边i->j,则在二分图中引入边i->j'。设二分图的最大匹配数为m,则结果就是n-m。

为什么呢?因为匹配和路径覆盖是一一对应的。对于路径覆盖中的每条简单路径,除了最后一个“结尾结点”之外都有唯一的后继和它对应(即匹配结点),因此匹配数就是非尾结点的个数。当匹配数达到最大时,非尾结点的个数也将达到最大。此时,结尾结点的个数最少,即路径条数最少。

// File Name: 1201.cpp
// Author: zlbing
// Created Time: 2013/3/1 20:40:52

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define MAXN 505
int Left[MAXN];//Left[i]为左边与右边第i个点匹配的编号
int w[MAXN][MAXN];
bool S[MAXN],T[MAXN];
int N;
struct Point{
    int t,a,b,c,d;
}cust[MAXN];
bool match(int i)
{
    S[i]=true;
    for(int j=1;j<=N;j++)if(w[i][j]&&!T[j])
    {
        T[j]=true;
        if(Left[j]==0||match(Left[j]))
        {
            Left[j]=i;
            return true;
        }
    }
    return false;
}

//返回的是最大匹配数

int hungry(){
    CL(Left,0);
    int sum=0;
    for(int i=1;i<=N;i++)
    {
        CL(S,0);
        CL(T,0);
        if(match(i))sum++;
    }
    return sum;
}
int count1(Point p)
{
    return abs(p.a-p.c)+abs(p.b-p.d);
}
int count2(Point p1,Point p2)
{
    return abs(p2.a-p1.c)+abs(p2.b-p1.d);
}
    
int main(){
    int cas=0;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d",&N);
        for(int i=1;i<=N;i++)
        {
            int t,tt,a,b,c,d;
            scanf("%d:%d %d %d %d %d",&t,&tt,&a,&b,&c,&d);
            tt+=t*60;
            cust[i].t=tt,cust[i].a=a,cust[i].b=b,cust[i].c=c,cust[i].d=d;
        }
        CL(w,0);
        for(int i=1;i<=N;i++)
            for(int j=i+1;j<=N;j++)
            {
                if(cust[i].t+count1(cust[i])+count2(cust[i],cust[j])<cust[j].t)
                    w[i][j]=1;
            }
        int ans=hungry();
        printf("%d\n",N-ans);
    }
    return 0;
}

 

posted @ 2013-03-01 21:18  z.arbitrary  阅读(305)  评论(0编辑  收藏  举报