码迷,mamicode.com
首页 > 编程语言 > 详细

F - Rain on your Parade - hdu 2389(二分图匹配,Hk算法)

时间:2015-08-03 14:28:13      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:

题意:给一些人和一些伞的坐标,然后每个人都有一定的速度,还有多少时间就会下雨,问最多能有多少人可以拿到伞。
分析:题意很明确,可以用每个人和伞判断一下是否能够达到,如果能就建立一个联系。不过这道题的数据还是挺大的,第一次使用的匈牙利算法果断的TLE了,然后就百度了一下发现有一个 Hopcroft-Karp算法 不过这个算法网上描述的很少,而且都说的比较含糊不清,不过幸好搜到一个比较不错的课件,看了一上午总算有些明白怎么回事,以前是寻找一个增广路,这个是寻找所有的增广路,并且使用BFS进行分层,看起来比较高大上,虽然我还是不明白怎么减少的复杂度(提交确实不不超时了).......后面做题在慢慢理解吧

课件连接

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

const int MAXN = 3005;
const int oo = 1e9+7;

struct point{int x, y, v;}p[MAXN], um;
bool OK(point a, point b, int v)
{///判断两点是否在合法范围内,也就是下雨前能否达到
    int len = (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);

    if(len > v*v)
        return false;
    return true;
}

struct Edge{int v, next;}e[MAXN*MAXN];
int Head[MAXN], cnt;
void AddEdge(int u, int v)
{///邻接表,点比较多,不好开邻接矩阵
    e[cnt].v = v;
    e[cnt].next = Head[u];
    Head[u] = cnt++;
}

bool used[MAXN];
int Mx[MAXN], My[MAXN];///记录的所匹配的端点,0表示未匹配
int dx[MAXN], dy[MAXN];///BFS分层时,记录点所在的层,-1表示不在分层
int Nx, Ny, depth;///Nx个人,Ny把雨伞, depth记录分层的深度

bool BFS()///如果发现y这边有增广路,返回1,否则返回0
{
    queue<int> Q; depth = oo;

    memset(dx, -1sizeof(dx));
    memset(dy, -1sizeof(dy));

    for(int i=1; i<=Nx; i++)
    {
        if( Mx[i] == false )
        {
            dx[i] = 0;
            Q.push(i);
        }
    }

    while(Q.size())
    {
        int x = Q.front(); Q.pop();
        if(dx[x] > depth) break;///已经找到了增广路,不必寻找下层

        for(int j=Head[x]; j!=-1; j=e[j].next)
        {
            int y = e[j].v;

            if( dy[y] == -1 )
            {
                dy[y] = dx[x] + 1;

                if(My[y] == false)
                    depth = dy[y];
                else
                {
                    dx[ My[y] ] = dy[y] + 1;
                    Q.push( My[y] );
                }
            }
        }
    }

    if( depth == oo )
        return false;
    return true;
}
bool Find(int i)
{
    for(int j=Head[i]; j!=-1; j=e[j].next)
    {
        int v = e[j].v;

        if( !used[v] && dx[i] == dy[v]-1)
        {
            used[v] = true;

            if( My[v] && dy[v] == depth )
                continue;///不会在下一层,因为还没有对下层进行增广

            if( !My[v] || Find( My[v] ) )
            {
                My[v] = i;
                Mx[i] = v;
                return true;
            }
        }
    }

    return false;
}

int Karp()
{
    int ans = 0;
    memset(Mx, falsesizeof(Mx));
    memset(My, falsesizeof(My));

    while( BFS() == true )
    {///如果还存在增广路
        memset(used, falsesizeof(used));
        for(int i=1; i<=Nx; i++)
        {
            if( !Mx[i] && Find(i) == true )
                ans++;
        }
    }

    return ans;
}

int main()
{
    int T, t=1;

    scanf("%d", &T);

    while(T--)
    {
        int i, j, time;

        scanf("%d%d", &time, &Nx);

        memset(Head, -1sizeof(Head));
        cnt = 0;

        for(i=1; i<=Nx; i++)
            scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].v);

        scanf("%d", &Ny);

        for(i=1; i<=Ny; i++)
        {
            scanf("%d%d", &um.x, &um.y);

            for(j=1; j<=Nx; j++)
            {
                if( OK(p[j], um, p[j].v*time) )
                    AddEdge(j, i);
            }
        }

        int ans = Karp();

        printf("Scenario #%d:\n", t++);
        printf("%d\n\n", ans);
    }

    return 0; 

}

 

F - Rain on your Parade - hdu 2389(二分图匹配,Hk算法)

标签:

原文地址:http://www.cnblogs.com/liuxin13/p/4699173.html

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