POJ 2060
题意
给出n个任务,每个任务是在规定的开始时间使 计程车 从二维平面A到达B点.并且求完成所有任务所需要的计程车的最少数量?
思路
将每个任务看做有向无环图中的一个点.如果上一个任务完成后能在另一个任务开始时间之前到达这个任务的起点.那么建有向边.为了完成所有任务(覆盖有向图所有的点)且调用的出租车最少(用最少的路径来覆盖有向图).问题转化成了最小路径覆盖
有向无环图最小路径覆盖定理: 路径条数 = n - 最大匹配数
证明略.可以找一个特例画图看看
样例:时间8:00开始花费6分钟.那么下次任务只能是从8:07开始
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std
;
const int maxn
= 505;
struct node
{int a
,b
,c
,d
,time
;}p
[maxn
];
vector
<int> v
[maxn
];
int match
[maxn
],time1
[maxn
],dis
[maxn
];
bool vis
[maxn
];
int n
;
int dfs(int u
) {
for (int i
=0; i
<v
[u
].size(); ++i
) {
int to
= v
[u
][i
];
if (!vis
[to
]) {
vis
[to
] = 1;
if (match
[to
]==-1 || dfs(match
[to
])) {
match
[to
] = u
;
return 1;
}
}
}
return 0;
}
int solve() {
int res
= 0;
memset(match
,-1,sizeof match
);
for (int i
=0; i
<n
; ++i
) {
memset(vis
,0,sizeof vis
);
res
+= dfs(i
);
}
return res
;
}
int main() {
freopen("1.in","r",stdin);
int times
; cin
>> times
;
int h
,m
;
while (times
--) {
scanf("%d",&n
);
for (int i
=0; i
<=n
; ++i
) v
[i
].clear();
for (int i
=0; i
<n
; ++i
) {
scanf("%d:%d %d%d%d%d",&h
,&m
,&p
[i
].a
,&p
[i
].b
,&p
[i
].c
,&p
[i
].d
);
p
[i
].time
= abs(p
[i
].a
-p
[i
].c
) + abs(p
[i
].b
- p
[i
].d
);
time1
[i
] = h
*60+m
;
for (int j
=0; j
<i
; ++j
)
if (time1
[i
]-time1
[j
]>p
[j
].time
+ abs(p
[i
].a
-p
[j
].c
) + abs(p
[i
].b
-p
[j
].d
))
v
[j
].push_back(i
);
}
printf("%d\n",n
-solve());
}
return 1;
}