poj3216Repairing Company 二分匹配之最小路径覆盖+floyd

//m个任务,每个任务都有开始时间和需要花的时间,以及其在哪楼地方工作
//给出地图,每楼到另一楼的路径所花的时间
//问最少需要安排多少人能完成这些任务
//对任务和任务之间建图,如果做完任务i还能做任务j那么i-j之间建立一条边
//这样只需要找到最小路径覆盖即为最终答案
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std ;
const int maxn = 210 ;
const int inf = 0x3f3f3f3f ;
int map[maxn][maxn] ;
int vis[maxn] ;
int match[maxn];
int dis[maxn][maxn] ;
struct node
{
    int st , id , ti ;
}t[maxn] ;
int n , m;
void floyd()
{
    for(int k = 1;k <= n;k++)
      for(int i = 1;i <= n;i++)
        for(int j = 1;j <= n;j++)
         dis[i][j] = min(dis[i][k] + dis[k][j] , dis[i][j]) ;
}
bool find(int st)
{
    for(int i = 1;i <= m;i++){
       if(!vis[i] && map[st][i]){
         vis[i] = 1 ;
         if(match[i] == -1 || find(match[i])){
            match[i] = st ;
            return true  ;
          }
       }
    }
    return false ;
}
int main()
{
    while(scanf("%d%d" , &n , &m) && (n+m))
    {
        memset(match , -1 , sizeof(match)) ;
        memset(map , 0 , sizeof(map)) ;
        for(int i = 1;i <= n;i++)
          for(int j = 1;j <= n;j++){
            scanf("%d" , &dis[i][j]);
            if(dis[i][j] == -1)
            dis[i][j] = inf ;
          }
        floyd() ;
        for(int i = 1;i <= m;i++)
        scanf("%d%d%d" , &t[i].id , &t[i].st , &t[i].ti) ;
        for(int i = 1;i <= m;i++){
          for(int j = 1;j <= m;j++){
             if(i == j) continue ;
             if(t[i].st + t[i].ti + dis[t[i].id][t[j].id] <= t[j].st)
             map[i][j] = 1 ;
          }
        }
        int ans = 0 ;
        for(int i = 1;i <= m;i++){
           memset(vis , 0 , sizeof(vis)) ;
           if(find(i))
           ans++ ;
        }
        cout<<m-ans<<endl;
    }
    return 0 ;
}







你可能感兴趣的:(floyd,二分匹配)