• 【LA3126 训练指南】出租车 【DAG最小路径覆盖】


    题意

      你在一座城市里负责一个大型活动的接待工作。明天将有m位客人从城市的不同的位置出发,到达他们各自的目的地。已知每个人的出发时间,出发地点和目的地。你的任务是用尽量少的出租车送他们,使得每次出租车接客人时,至少能提前一分钟到达他所在的位置。注意,为了满足这一条件,要么这位客人是这辆出租车接送的第一个人,要么在接送完上一个客人后,有足够的时间从上一个目的地开到这里。

      为了简单起见,假定城区是网格型的,地址用坐标(x,y)表示,出租车从(x1,y1)到(x2,y2)处需要行驶|x1-x2|+|y1-y2|分钟。

    分析

      这个模型叫做DAG的最小路径覆盖。所谓最小路径覆盖,就是在图中找尽量少的路径,使得每个结点恰好在一条路径上(换句话说,不同的路径不能有公共点)。注意,单独的一个结点也可以作为一条路径。

      DAG最小路径覆盖的解法如下:把所有的结点i拆为X结点i和Y结点i‘,如果图G中存在有向边i->j,则二分图中引入边i->j'。设二分图的最大匹配数为m,则结果就是n-m。因为匹配和路径覆盖是一一对应的。对于路径覆盖中的每条简单路径,除了最后一个“结尾结点”以外都有唯一的后继和他对应(既匹配结点),因此匹配数就是非结尾结点的个数,当匹配数达到最大时,此时,结尾结点的个数最少,既路径条数最少。

     

     本题建模:每个客人是一个结点,如果同一个出租车接完客人u以后还来得及接客人v,连边u->v。不难发现,这个图是一个DAG,并且它的最小路径覆盖就是本题的答案。

     

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <queue>
      6 #include <cmath>
      7 
      8 using namespace std;
      9 const int maxn=3000+10;
     10 const int maxm=800000;
     11 const int INF=2147483600;
     12 struct Dinic{
     13     int head[maxn],Next[maxm],to[maxm],cap[maxm],flow[maxm];
     14     int sz,n,m,s,t;
     15     bool vis[maxn];
     16     int cur[maxn],d[maxn];
     17     void init(int n){
     18         this->n=n;
     19         memset(head,-1,sizeof(head));
     20         this->sz=-1;
     21     }
     22     void add_edge(int a,int b,int c){
     23         ++sz;
     24         to[sz]=b;
     25         cap[sz]=c;flow[sz]=0;
     26         Next[sz]=head[a];head[a]=sz;
     27         ++sz;
     28         to[sz]=a;
     29         cap[sz]=c;flow[sz]=c;
     30         Next[sz]=head[b];head[b]=sz;
     31     }
     32     bool BFS(){
     33         memset(vis,0,sizeof(vis));
     34         queue<int>Q;
     35         vis[s]=1;
     36         d[s]=0;
     37         Q.push(s);
     38         while(!Q.empty()){
     39             int u=Q.front();Q.pop();
     40             for(int i=head[u];i!=-1;i=Next[i]){
     41                 int v=to[i];
     42                 if(!vis[v]&&cap[i]>flow[i]){
     43                     vis[v]=1;
     44                     d[v]=d[u]+1;
     45                     Q.push(v);
     46                 }
     47             }
     48         }
     49         return vis[t];
     50    }
     51     int DFS(int x,int a){
     52         if(x==t||a==0)return a;
     53         int Flow=0,f;
     54         for(int& i=cur[x];i!=-1;i=Next[i]){
     55             int v=to[i];
     56             if(d[v]==d[x]+1&&(f=DFS(v,min(a,cap[i]-flow[i])))>0){
     57                 Flow+=f;
     58                 flow[i]+=f;
     59                 flow[i^1]-=f;
     60                 a-=f;
     61                 if(a==0)break;
     62             }
     63         }
     64         return Flow;
     65     }
     66     int Maxflow(int s,int t){
     67         this->s=s,this->t=t;
     68         int Flow=0;
     69         while(BFS()){
     70             for(int i=0;i<=n;i++)
     71              cur[i]=head[i];
     72 
     73             Flow+=DFS(s,INF);
     74         }
     75         return Flow;
     76     }
     77 }dinic;
     78 int T,m;
     79 int sth[maxn],stm[maxn],sx[maxn],sy[maxn],enx[maxn],eny[maxn];
     80 int dist(int x1,int y1,int x2,int y2){
     81     return abs(x1-x2)+abs(y1-y2);
     82 }
     83 void pass_time(int hou,int mi,int &Hou,int &Mi,int tim){
     84     Mi=mi+tim;
     85     Hou=hou+Mi/60;
     86     Mi=Mi%60;
     87     return;
     88 }
     89 int main(){
     90     scanf("%d",&T);
     91     for(int t=1;t<=T;t++){
     92         scanf("%d",&m);
     93         dinic.init(2*m+5);
     94         for(int i=1;i<=m;i++){
     95             scanf("%d:%d%d%d%d%d",&sth[i],&stm[i],&sx[i],&sy[i],&enx[i],&eny[i]);
     96         }
     97 
     98         for(int i=1;i<=m;i++){
     99             for(int j=1;j<=m;j++){
    100                 int tim=dist(sx[i],sy[i],enx[i],eny[i])+dist(enx[i],eny[i],sx[j],sy[j]);
    101                 int Enh,Enm;
    102                 pass_time(sth[i],stm[i],Enh,Enm,tim);
    103                 if(Enh*60+Enm>=sth[j]*60+stm[j])continue;
    104                 dinic.add_edge(i,j+m,1);
    105             }
    106         }
    107         for(int i=1;i<=m;i++)
    108           dinic.add_edge(0,i,1);
    109         for(int i=1;i<=m;i++)
    110           dinic.add_edge(i+m,2*m+1,1);
    111         int ans=dinic.Maxflow(0,2*m+1);
    112         printf("%d
    ",m-ans);
    113 
    114     }
    115 return 0;
    116 }
    View Code
  • 相关阅读:
    python中的一些小知识
    软件工程第一次作业(2)
    CountDownLatch的理解和使用
    架构设计:系统间通信(1)概述从“聊天”开始上篇
    Asp默认的上传文件大小限制是200K
    当多个sqlserver服务存在时,需要完全限定的serverName 方可登陆
    关于Entity Framework 版本的疑惑
    mvc scaffolding
    sql 语句中的 NULL值
    如何从数据库生成 EF Code First model
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9307511.html
Copyright © 2020-2023  润新知