题目大意:
有Q个地点,告诉你Q个地点之间的相互距离(从i地点赶到j地点需要的时间)。有M项任务,
给你M项任务所在的地点block、开始时间start和任务完成需要时间time。一个工人只有在
他准备完成的下一项任务开始之前完成手上的任务,然后在下一项任务开始之前赶到下一项
任务的地点,才能完成这两项任务。问:最少需要多少个工人来完成这M项任务。
/* 对于这类二分图的最小路径覆盖,我是这么理解的: 那这道题来说,我们可以先假设一共需要m个工人,然后经过二分图匹配, 每匹配一对,说明有两项任务可以由一个工人完成,m就减1,最后,剩下 的m即为所求 */ #include<cstdio> #include<iostream> #include<cstring> #define M 210 #define N 22 using namespace std; int map[N][N],used[M],belong[M],a[M][M],q,m; struct node { int pos,begin,end; };node e[M]; void Floyed() { for(int k=1;k<=q;k++) for(int i=1;i<=q;i++) for(int j=1;j<=q;j++) if(i!=j&&i!=k&&j!=k) map[i][j]=min(map[i][k]+map[k][j],map[i][j]); } int find(int i) { for(int j=1;j<=m;j++) if(!used[j]&&a[i][j]) { used[j]=1; if(!belong[j]||find(belong[j])) { belong[j]=i; return 1; } } return 0; } int main() { while(1) { memset(map,0x3f3f3f3f,sizeof(map)); memset(used,0,sizeof(used)); memset(belong,0,sizeof(belong)); memset(a,0,sizeof(a)); scanf("%d%d",&q,&m); if(q==0&&m==0)break; for(int i=1;i<=q;i++) for(int j=1;j<=q;j++) { int x; scanf("%d",&x); if(x!=-1) map[i][j]=map[j][i]=x; } Floyed(); for(int i=1;i<=m;i++) { int x; scanf("%d%d%d",&e[i].pos,&e[i].begin,&x); e[i].end=e[i].begin+x; } for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) if(i!=j&&e[j].begin-e[i].end>=map[e[i].pos][e[j].pos]) a[i][j]=1; int tot=0; for(int i=1;i<=m;i++) if(find(i)) { memset(used,0,sizeof(used)); tot++; } printf("%d\n",m-tot); } return 0; }