P5769 [JSOI2016] 飞机调度
P5769\(\mathbf{} \begin{Bmatrix} \frac{{\Large LUOGU-P5769} }{{\color{Red}\Large Solution} }\mathbf{} {No.5} \end{Bmatrix}\times{}\) NeeDna
这道题最重要的就是建模 发现本题求的是需要多少架飞机才能完成任务 联想到二分图最大匹配 由此我们开始建模。
首先我们把飞机看成边,机场看成点。所以我们就会有一种思路:把所有可行的航班连起来,看目前的飞机能满足多少线路。再用所有航班减去可行的答案就是所需要的增加的答案了。
如何计算可行答案?先思考最简单的情况。飞机航班需要满足不会迟到、延误航班才行。所以我们为了满足最多的可能,才可以找到最优秀的答案。我们用floyd算法跑一次所有点之间的最短路。
然后因为有维修时间(发现和机场绑定,所以一起算)。
接下来,我们来计算一个架次是否能成立。开始的时间是起始的飞机场的起飞时间 接下来飞机会经过(飞行)(维修和飞行)(维修)三部分 加起来小于终点的起飞时间 部分代码如下:
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
if(i^j&&e[i].w+t[e[i].u][e[i].v]+p[e[i].v]+l[e[i].v][e[j].u]<=e[j].w){
f[i][j]=1;
}
}
}
然后其实这就是一个DAG最小路径覆盖了,不懂的luogu上有模版。简单来说做完建图后把每一条边放到二分图最大匹配里即可(即为起点向终点连边)。
AC code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e3+10;
int n,m,vis[N],ma[N],ans=0,f[N][N];
int t[N][N],p[N],l[N][N];
struct node{
int u,v,w;
}e[N<<1];
int dfs(int x){
for(int i=1;i<=m;i++){
if(vis[i]||!f[x][i]) continue;
vis[i]=1;
if(!ma[i]||dfs(ma[i])){
ma[i]=x;
return 1;
}
}
return 0;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){cin>>p[i];}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>t[i][j];
if(i^j) l[i][j]=p[j]+t[i][j];
}
}
for(int i=1;i<=m;i++){
cin>>e[i].u>>e[i].v>>e[i].w;
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
l[i][j]=min(l[i][j],l[i][k]+l[k][j]);
}
}
}
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
if(i^j&&e[i].w+t[e[i].u][e[i].v]+p[e[i].v]+l[e[i].v][e[j].u]<=e[j].w){
f[i][j]=1;
}
}
}
for(int i=1;i<=m;i++){
memset(vis,0,sizeof(vis));
ans+=dfs(i);
}
cout<<m-ans;
return 0;
}

浙公网安备 33010602011771号