POJ 3216 Repairing Company 最少路径覆盖+floyd最短路

 
 
不同的任务分散在不同的地点,每个任务都有开始时间和消耗时长,必须完成一个任务才可能接下一个任务,问最少需要几个人来完成这些任务。 可以将任务当作点,那么两个任务a,b之间有一条边意味着完成a任务之后可以接着完成b任务,以此来建图。 对于两个任务a,b,如果他们之间有一条边<a,b>,那么首先a的开始时间加消耗时长再加上从a到b所花费的时间必须小于等于b的开始时间。但是题目给出的两点之间的距离并不一定是最短的,因此要先求一下最短路径,由于点数很少,我们直接使用floyd求任意两点之间的最短距离,然后再对建出的图进行二分最大匹配,ans=n-hungary()。
Repairing Company
Time Limit: 1000MSMemory Limit: 131072K
Total Submissions: 6931Accepted: 1863

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 pi, ti 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

Source

 
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

const int MAXN=510;
const int INF=99999999;

struct Task
{
    int p,t,d;
};

Task task[MAXN];
int tN;
int uN,vN;
int g[MAXN][MAXN];
int linker[MAXN];
bool used[MAXN];
int cost[30][30];
int Q,M;

bool dfs(int u)
{
    for(int v=0; v<vN; v++)
        if(g[u][v]&&!used[v])
        {
            used[v]=true;
            if(linker[v]==-1||dfs(linker[v]))
            {
                linker[v]=u;
                return true;
            }
        }
    return false;
}

int hungary()
{
    int res=0;
    memset(linker,-1,sizeof(linker));
    for(int u=0; u<uN; u++)
    {
        memset(used,false,sizeof(used));
        if(dfs(u))
            res++;
    }
    return res;
}

void init()
{
    tN=0;
    memset(g,0,sizeof(g));
}

void addtask(int p,int t,int d)
{
    task[tN].p=p;
    task[tN].t=t;
    task[tN].d=d;
    tN++;
}

bool judge(Task a,Task b)
{
    if(cost[a.p][b.p]==-1)
        return false;
    int tt=a.d+a.t+cost[a.p][b.p];
    if(tt<=b.d)
        return true;
    return false;
}

void floyd()
{
    for(int k = 0; k < Q; ++k)
        for(int i = 0; i < Q; ++i)
            for(int j = 0; j < Q; ++j)
                cost[i][j] = cost[i][j] < cost[i][k]+cost[k][j]?cost[i][j]:cost[i][k]+cost[k][j];
}

void show()
{
    for(int i=0;i<Q;i++)
    {
        for(int j=0;j<Q;j++)
        {
            printf("%d ",cost[i][j]);
        }
        printf("\n");
    }
}


int main()
{

    int p,t,d;
    int ans;
    while(~scanf("%d%d",&Q,&M)&&(Q||M))
    {
        init();
        for(int i=0; i<Q; i++)
            for(int j=0; j<Q; j++)
            {
                scanf("%d",&cost[i][j]);
                if(cost[i][j]==-1)
                    cost[i][j]=INF;
            }

        floyd();
        //show();
        for(int i=0; i<M; i++)
        {
            scanf("%d%d%d",&p,&d,&t);
            addtask(p-1,t,d);
        }
        uN=vN=tN;
        for(int i=0; i<tN; i++)
        {
            for(int j=0; j<tN; j++)
            {
                if(judge(task[i],task[j]))
                {
                    g[i][j]=1;
                }
                if(judge(task[j],task[i]))
                {
                    g[j][i]=1;
                }
            }
        }
        ans=tN-hungary();
        printf("%d\n",ans);
    }
}
 

查看原文:http://colorfulshark.cn/wordpress/repair-company-1001.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值