码迷,mamicode.com
首页 > 其他好文 > 详细

POJ3216 Repairing Company【二分图最小路径覆盖】【Floyd】

时间:2015-04-07 19:44:05      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:

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


题目大意:

有Q个地点,告诉你Q个地点之间的相互距离(从i地点赶到j地点需要的时间)。有M项任务,

给你M项任务所在的地点block、开始时间start和任务完成需要时间time。一个工人只有在

他准备完成的下一项任务开始之前完成手上的任务,然后在下一项任务开始之前赶到下一项

任务的地点,才能完成这两项任务。问:最少需要多少个工人来完成这M项任务。


思路:

先用Floyd算出Q个地点之间相互最短距离。然后建立一个二分图,每边都是M项任务,如果

能在任务j完成之前将i任务完成并能赶到任务j的地点,就建立一条边。那么问题就变为了求

二分图最小路径覆盖问题。而二分图最小路径覆盖 = 点数 - 二分图最大匹配。二分图最大匹

配用匈牙利算法来求。


AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 25;
const int MAXM = 220;
const int INF = 0xffffff0;

int G[MAXN][MAXN],Dist[MAXN][MAXN];

struct Node
{
    int block;
    int start;
    int time;
}node[MAXM];

void Floyd(int N)
{
    for(int i = 1; i <= N; ++i)
        for(int j = 1; j <= N; ++j)
            Dist[i][j] = G[i][j];

    for(int k = 1; k <= N; ++k)
        for(int i = 1; i <= N; ++i)
            for(int j = 1; j <= N; ++j)
                if(Dist[i][k] + Dist[k][j] < Dist[i][j])    //加Dist[i][j] != INF && Dist[k][j] != INF出错。。。
                    Dist[i][j] = Dist[i][k] + Dist[k][j];

}

bool Map[MAXM][MAXM],Mask[MAXM];
int NX,NY;
int cx[MAXM],cy[MAXM];

int FindPath(int u)
{
    for(int i = 1; i <= NY; ++i)
    {
        if(Map[u][i] && !Mask[i])
        {
            Mask[i] = 1;
            if(cy[i] == -1 || FindPath(cy[i]))
            {
                cy[i] = u;
                cx[u] = i;
                return 1;
            }
        }
    }
    return 0;
}

int MaxMatch()
{
    for(int i = 1; i <= NX; ++i)
        cx[i] = -1;
    for(int i = 1; i <= NY; ++i)
        cy[i] = -1;

    int res = 0;
    for(int i = 1; i <= NX; ++i)
    {
        if(cx[i] == -1)
        {
            for(int j = 1; j <= NY; ++j)
                Mask[j] = 0;
            res += FindPath(i);
        }
    }
    return res;
}

int main()
{
    int Q,M;
    while(~scanf("%d%d",&Q,&M) && (Q||M))
    {
        for(int i = 1; i <= Q; ++i)
        {
            for(int j = 1; j <= Q; ++j)
            {
                scanf("%d",&G[i][j]);
                if(G[i][j] == -1)
                    G[i][j] = INF;
            }
        }
        for(int i = 1; i <= M; ++i)
            scanf("%d%d%d",&node[i].block,&node[i].start,&node[i].time);

        Floyd(Q);
        memset(Map,0,sizeof(Map));
        for(int i = 1; i <= M; ++i)
        {
            for(int j = 1; j <= M; ++j)
            {
                int u = node[i].block;
                int v = node[j].block;
                if(i != j && Dist[u][v] != INF)
                {
                    if(node[i].start + node[i].time + Dist[u][v] <= node[j].start)
                        Map[i][j] = 1;
                }
            }
        }
        NX = NY = M;
        printf("%d\n",M-MaxMatch());
    }

    return 0;
}


POJ3216 Repairing Company【二分图最小路径覆盖】【Floyd】

标签:

原文地址:http://blog.csdn.net/lianai911/article/details/44923549

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!