题意:给定n条街道,用一个矩阵描述两两之间的距离,m个任务,p,t,d分别为所在街道、任务起始时间、任务结束时间,求完成所有任务所需最少人数;
思路:先用floyd处理两两间最短路,然后,若完成i任务的人能够完成j任务,则在i,j间建一条边,所需人数为总任务数减最大匹配数;匈牙利算法;
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f struct node { int p,t,d; }q[500010]; int n,m; int link[5500],vis[5500]; int mm[550][550],g[550][550]; int dfs(int t)//增广路 { int i,j,k; for(i=1;i<=m;i++) { if(g[t][i]&&!vis[i]) { vis[i]=1; if(link[i]==-1||dfs(link[i])) { link[i]=t; return 1;//找到新增广路 } } } return 0; } int hungry()//最大匹配数 { int i,j,k,num=0; memset(link,-1,sizeof(link)); for(i=1;i<=m;i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) num++; } return num; } int main() { int i,j,k; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; memset(mm,0,sizeof(mm)); memset(g,0,sizeof(g)); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { scanf("%d",&mm[i][j]); if(mm[i][j]==-1) mm[i][j]=INF; } } for(i=1;i<=m;i++) { scanf("%d%d%d",&q[i].p,&q[i].t,&q[i].d); } for(i=1;i<=n;i++)//floyd算各点间最短路 { for(j=1;j<=n;j++) { for(k=1;k<=n;k++) { if(mm[j][k]>mm[j][i]+mm[i][k]) mm[j][k]=mm[j][i]+mm[i][k]; } } } for(i=1;i<=m;i++)//构建二分图 { for(j=1;j<=m;j++) { int u=q[i].p; int v=q[j].p; if(i==j||mm[u][v]==INF) continue; if(q[i].t+q[i].d+mm[u][v]<=q[j].t) g[i][j]=1; } } printf("%d ",m-hungry()); } return 0; }