【GDOI模拟】飞机调度
来源:互联网 发布:淘宝赚佣金软件叫什么 编辑:程序博客网 时间:2024/04/28 17:31
Description
作为一个旅行达人以及航空公司的金卡会员,你每一年的飞行里程可以绕赤道几周了。你发现,航空公司为了提高飞机的使用率,并不是简单的一条航线使用一架飞机来回飞,而是会让同一架飞机连续不停地飞不同的航线,甚至有的时候为了能够完成飞机的调度,航空公司还会增开一些临时航线——在飞机转场的同时顺路捎一些乘客。你研究了一下GDOI著名航空公司GD Airways的常规直飞航线,你想知道,在最佳调度方案下,GD Airways最少需要多少架飞机才能成功执飞这所有的航线。
GDOI王国里有N个机场,编号为1到N。从i号机场到j号机场需要飞行Ti,j的时间。由于风向,地理位置和航空管制的因素,Ti,j和Tj,i并不一定相同。
此外,由于飞机降落之后需要例行维修和加油。当一架飞机降落k号机场时,需要花费Pk的维护时间才能再次起飞。
GD Airways一共运营M条航线,其中第i条直飞航线需要在Di时刻从Xi机场起飞,不经停,飞往Yi机场。
为了简化问题,我们假设GD Airways可以在0时刻在任意机场任意多架加油维护完毕的飞机;为了减少飞机的使用数,我们允许GD Airways增开任意多条临时航线以满足飞机的调度需要。
你想知道,理论上GD Airways最少需要多少架飞机才能完成所有这M个航班。
Solution
一眼就可以看出来是最小路径覆盖。
根据常识最小路径覆盖=节点个数-最大匹配
如果航班i的飞机可以及时飞到航班j,那么就可以把i向j连边。
然后可以用KM算法(匈牙利算法),也可以打一个最大流。
其实还有一个贪心的算法(不知道是不是水的),这里就不谈了。
Code
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=1007;int i,j,k,l,t,n,m,ans,S,T;int first[maxn*maxn],next[maxn*maxn],last[maxn*maxn],chang[maxn*maxn];int p[maxn*maxn],a[maxn][maxn],f[maxn][maxn],d[maxn],fan[maxn*maxn],num;int data[maxn*maxn],b[maxn*maxn],c[maxn*maxn],dd[maxn*maxn],dis[maxn*maxn];void add(int x,int y,int z){ last[++num]=y; next[num]=first[x]; first[x]=num; chang[num]=z; fan[num]=num+1; last[++num]=x; next[num]=first[y]; first[y]=num; chang[num]=0; fan[num]=num-1;}bool bfs(){ int head=0,tail=1,now,i,ber; memset(data,0,sizeof(data)); memset(d,0,sizeof(d));d[S]=1; ber=d[0]; data[1]=S; while(head<tail){ now=data[++head]; for(i=first[now];i;i=next[i]){ if(!d[last[i]]&&chang[i]>0){ d[last[i]]=d[now]+1; data[++tail]=last[i]; } } } return d[T]!=0;}int dinic(int x,int y){ int i,j,k=0,l=0; if(x==T){ return y; } for(i=first[x];i;i=next[i]){ if(d[x]+1==d[last[i]]&&chang[i]>0){ if(chang[i]>y)k=dinic(last[i],y); else k=dinic(last[i],chang[i]); if(k){ l+=k; chang[i]-=k;chang[fan[i]]+=k; y-=k; if(y==0)break; } } } if(l==0)d[x]=-1; return l;}int main(){ freopen("flight.in","r",stdin); freopen("flight.out","w",stdout); scanf("%d%d",&n,&m); fo(i,1,n)scanf("%d",&p[i]); S=0,T=2*m+1; memset(f,127,sizeof(f)); fo(i,1,n)fo(j,1,n){ scanf("%d",&a[i][j]); if(i==j)f[i][j]=a[i][j]; else f[i][j]=a[i][j]+p[j]; } fo(k,1,n){ fo(i,1,n){ fo(j,1,n){ if(i==j)continue; if(f[i][k]+f[k][j]<f[i][j]){ f[i][j]=f[i][k]+f[k][j]; } } } } fo(i,1,m){ scanf("%d%d%d",&b[i],&c[i],&dd[i]); add(S,i,1);add(i+m,T,1); } fo(i,1,m){ fo(j,1,m){ if(i==j)continue; if(dd[i]+a[b[i]][c[i]]+p[c[i]]+f[c[i]][b[j]]<=dd[j]){ add(i,j+m,1); } } } ans=m; while(bfs())ans-=dinic(S,0x7fffffff); printf("%d\n",ans);}
1 0
- 【GDOI模拟】飞机调度
- 【GDOI2016模拟4.22】飞机调度
- 【GDOI2016模拟4.23】飞机调度
- JZOJ 4465【GDOI2016模拟4.22】飞机调度
- 飞机调度
- JZOJ.4465[GDOI2016模拟4.22] 飞机调度 解题报告
- GDOI 3.21 模拟总结
- 【GDOI】模拟8.1总结
- 【GDOI】模拟8.2总结
- 【GDOI】模拟8.3总结
- GDOI模拟8.1
- 【GDOI 2013模拟】屏保
- GDOI模拟 20150806
- GDOI模拟8.6总结
- GDOI模拟8.7总结
- 【GDOI 2013模拟】Processer
- GDOI模拟 蜘蛛侠
- 【GDOI 2013模拟】总结
- Android资源混淆打包工具 - 让你的资源瘦瘦身
- 什么是单糖
- Java学习笔记-动态加载类
- 【Android学习】IPC 基础概念(序列化接口介绍)
- 什么是双糖
- 【GDOI模拟】飞机调度
- 接口的使用
- 二叉树的数组表示 C++实现(添加 按层遍历)
- 易被遗忘的C/C++要点总结
- 读《从优秀到卓越》乱摘
- SQLServer 2012+win10安装记录
- UVALive - 4845 组合数
- 线段树专题
- solr入门之多线程默认查询solr库的返回结果不一致问题