zoukankan      html  css  js  c++  java
  • poj 3216 Repairing Company(最短路Floyd + 最小路径覆盖 + 构图)

    http://poj.org/problem?id=3216

    Repairing Company
    Time Limit: 1000MS   Memory Limit: 131072K
    Total Submissions: 6776   Accepted: 1822

    Description

    Lily runs a repairing company that services the Q blocks in the city. One day the company receives M repair tasks, the ith of which occurs in block pi, has a deadline ti on any repairman’s arrival, which is also its starting time, and takes a single repairman di time to finish. Repairmen work alone on all tasks and must finish one task before moving on to another. With a map of the city in hand, Lily want to know the minimum number of repairmen that have to be assign to this day’s tasks.

    Input

    The input contains multiple test cases. Each test case begins with a line containing Q and M (0 < Q ≤ 20, 0 < M ≤ 200). Then follow Q lines each with Q integers, which represent a Q × Q matrix Δ = {δij}, where δij means a bidirectional road connects the ith and the jth blocks and requires δij time to go from one end to another. If δij = −1, such a road does not exist. The matrix is symmetric and all its diagonal elements are zeroes. Right below the matrix are M lines describing the repairing tasks. The ith of these lines contains piti and di. Two zeroes on a separate line come after the last test case.

    Output

    For each test case output one line containing the minimum number of repairmen that have to be assigned.

    Sample Input

    1 2
    0
    1 1 10
    1 5 10
    0 0

    Sample Output

    2

    题目大意:Lily管理q个地方(q*q的矩阵,maps[i][j]表示地点i到j花费的时间),她接到m个任务

    每个任务i,该任务的执行的地点为pi,执行人员到达花费时间ti(也是该任务i开始的时间),完成该任务

    花费时间di,执行人员完成了上一个任务下能去做下一个任务(即执行人员要想做第j个任务,他完成上一

    个任务i花的所有时间+到达第j个任务发生的地点所花的时间<=第j个任务开始的时间);求最少需要多少

    执行人员去执行这m个任务


    用Floyd来找到地点i到地点j花费的最少时间即最短路(即可以缩短执行人员从i地到j地在路上的时间)

    然后用二分匹配,注意二分图的X集合和Y集合都是任务的编号,而不是任务执行的地点如果第i个任务完成

    后还能做第j个任务,则i与j之间有一条连线G[i][j] = 1

    接下来就是二分匹配的最小覆盖路经问题了

    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<stdlib.h>
    #include<algorithm>
    #define N 310
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    struct node
    {
        int p, t, d;
    }node[N];
    
    int G[N][N], maps[30][30], vis[N], used[N];
    int m, q;
    
    bool Find(int u)
    {
        int i;
        for(i = 1 ; i <= m ; i++)
        {
            if(!vis[i] && G[u][i])
            {
                vis[i] = 1;
                if(!used[i] || Find(used[i]))
                {
                    used[i] = u;
                    return true;
                }
            }
        }
        return false;
    }
    
    void Floyd()
    {
        int i, j, k;
        for(k = 1 ; k <= q ; k++)
        {
            for(i = 1 ; i <= q ; i++)
            {
                for(j = 1 ; j <= q ; j++)
                {
                    if(maps[i][k] + maps[k][j] < maps[i][j])
                        maps[i][j] = maps[i][k] + maps[k][j];
                }
            }
        }
    }
    
    int main()
    {
        int i, j;
        while(scanf("%d%d", &q, &m), q + m)
        {
            memset(G, 0, sizeof(G));
            for(i = 1 ; i <= q ; i++)
            {
                for(j = 1 ; j <= q ; j++)
                  {
                      scanf("%d", &maps[i][j]);
                      if(maps[i][j] == -1)
                        maps[i][j] = INF;
                  }
            }
            for(i = 1 ; i <= m ; i++)
                scanf("%d%d%d", &node[i].p, &node[i].t, &node[i].d);
            Floyd();
            for(i = 1 ; i <= m ; i++)
            {
                for(j = 1 ; j <= m ; j++)
                {
                    if(i == j)continue;
                    if(node[i].d + maps[node[i].p][node[j].p] + node[i].t <= node[j].t)
                        G[i][j] = 1;//****注意此处二分图的两个集合元素是任务的编号而不是地点block
                }
            }
            int ans = 0;
            memset(used, 0, sizeof(used));
            for(i = 1 ; i <= m ; i++)
            {
                memset(vis, 0, sizeof(vis));
                if(Find(i))
                    ans++;
            }
            printf("%d
    ", m - ans);
        }
        return 0;
    }
     
  • 相关阅读:
    Windows Azure 社区新闻综述(#64 版)
    Eclipse下配置C/C++开发环境
    有你同行,我不会寂寞物联网操作系统Hello China后续开发计划及开发者征集
    ObjectiveC新手推荐《ObjectiveC开发范例代码大全》
    虚拟网络添加跨界连接的新功能
    WebMatrix 3发布了!
    Windows Live最值得期待的功能 FolderShare
    ASP.NET 2.0 两种模式website和web application到底那个好?
    Sonata 1.2.1 发布
    DB2 9 使用拓荒(733 测验)认证指南,第 9 部分: 用户定义的例程(4)
  • 原文地址:https://www.cnblogs.com/qq2424260747/p/4840570.html
Copyright © 2011-2022 走看看