二分图最大匹配hopcroft-karp算法——HDU 2389

对应HDU题目:点击打开链接

Rain on your Parade

Time Limit: 3000MS   Memory Limit: 165535KB   64bit IO Format: %I64d & %I64u

Submit Status

Description

You’re giving a party in the garden of your villa by the sea. The party is a huge success, and everyone is here. It’s a warm, sunny evening, and a soothing wind sends fresh, salty air from the sea. The evening is progressing just
as you had imagined. It could be the perfect end of a beautiful day.

But nothing ever is perfect. One of your guests works in weather forecasting. He suddenly yells, “I know that breeze! It means its going to rain heavily in just a few minutes!” Your guests all wear their best dresses and really would not like to get wet, hence
they stand terrified when hearing the bad news.

You have prepared a few umbrellas which can protect a few of your guests. The umbrellas are small, and since your guests are all slightly snobbish, no guest will share an umbrella with other guests. The umbrellas are spread across your (gigantic) garden, just
like your guests. To complicate matters even more, some of your guests can’t run as fast as the others.

Can you help your guests so that as many as possible find an umbrella before it starts to pour?

Given the positions and speeds of all your guests, the positions of the umbrellas, and the time until it starts to rain, find out how many of your guests can at most reach an umbrella. Two guests do not want to share an umbrella, however.

Input

The input starts with a line containing a single integer, the number of test cases.

Each test case starts with a line containing the time t in minutes until it will start to rain (1 <=t <= 5). The next line contains the number of guests m (1 <= m <= 3000), followed by m lines containing x- and y-coordinates as well as the speed si in units
per minute (1 <= s i <= 3000) of the guest as integers, separated by spaces. After the guests, a single line contains n (1 <= n <= 3000), the number of umbrellas, followed by n lines containing the integer coordinates of each umbrella, separated
by a space.

The absolute value of all coordinates is less than 10000.

Output

For each test case, write a line containing “Scenario #i:”, where i is the number of the test case starting at 1. Then, write a single line that contains the number of guests that can at most reach an umbrella before it starts to
rain. Terminate every test case with a blank line.

Sample Input

 2
1
2
1 0 3
3 0 3
2
4 0
6 0
1
2
1 1 2
3 3 2
2
2 2
4 4 

Sample Output

 Scenario #1:
2

Scenario #2:
2 

Source

题意:在一个二维坐标系上有n个人和m把伞,每个人都有自己的移动速度,问最多有多少人可以再t min内移动到不同的雨伞处(不允许两个人共用一把伞)。

思路:很明显是二分图的最大匹配问题,用普通DFS,BFS匈牙利算法妥当TLE,之后学了Hopcroft-Karp算法后回来再做;

有点奇怪的是用邻接矩阵无论是效率或空间都比邻接表或vector要好。。。

贴上邻接表代码:

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#define ms(x,y) memset(x,y,sizeof(x))
const int MAXN=3000+10;
const int MAX=9000000+10;
const int INF=1<<30;
using namespace std;
int time,n,m;
int speed[MAXN];
int head[MAXN];
int vis[MAXN];
int dx[MAXN];
int dy[MAXN];
int link_l[MAXN];
int link_r[MAXN];
int dis;

struct Edge
{
    int v,next;
}E[MAX];

struct COOR
{
    int x,y;
}N[MAXN], M[MAXN];

bool Search()
{
    queue<int>q;
    dis = INF;
    ms(dx, -1);
    ms(dy, -1);
    for(int i = 0; i<n; i++)
        if(link_r[i] == -1){//未匹配点入队,该点层次为0
            q.push(i);
            dx[i] = 0;
        }
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        if(dx[u] > dis) break;//层次大于该次搜索最小增广路层次,退出
        for(int i = head[u]; i != -1; i = E[i].next){
            int v = E[i].v;
            if(dy[v] == -1){//v是未匹配点
                dy[v] = dx[u] + 1;
                if(link_l[v] == -1) dis = dy[v];//找到一条最小增广路
                else{
                    dx[link_l[v]] = dy[v] + 1;
                    q.push(link_l[v]);
                }
            }
        }
    }
    return dis != INF;
}

int dfs(int u)
{
    for(int i=head[u]; i != -1; i = E[i].next){
        int v = E[i].v;
        if(!vis[v] && dy[v] == dx[u] + 1){
            vis[v] = 1;
            if(link_l[v] != -1 && dy[v] == dis) continue;//层次(也就是增广路径的长度)大于本次查找的dis,是searchP被break的情况,也就是还不确定是否是增广路径,只有等再次调用searchP()在判断。
            if(link_l[v] == -1 || dfs(link_l[v])){
                link_l[v] = u;
                link_r[u] = v;
                return 1;
            }
        }
    }
    return 0;
}

int MaxMatch()
{
    int res = 0;
    ms(link_l, -1);
    ms(link_r, -1);
    while(Search())
    {
        ms(vis, 0);
        for(int i=0; i<n; i++)
            if(link_r[i] == -1) res += dfs(i);
    }
    return res;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int T, w = 0;;
    scanf("%d", &T);
    while(T--)
    {
        ms(head, -1);
        int size = 0;
        scanf("%d%d", &time, &n);
        for(int i=0; i<n; i++)
            scanf("%d%d%d", &N[i].x, &N[i].y, &speed[i]);
        scanf("%d", &m);
        for(int i=0; i<m; i++)
            scanf("%d%d", &M[i].x, &M[i].y);
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                if((N[i].x - M[j].x) * (N[i].x - M[j].x) + (N[i].y - M[j].y) * (N[i].y - M[j].y) <= time * speed[i] * time * speed[i]){
                    E[size].v = j;
                    E[size].next = head[i];
                    head[i] = size++;
                }
            }
        }
        printf("Scenario #%d:\n%d\n\n", ++w, MaxMatch());
    }
    return 0;
}
时间: 2024-11-08 20:47:26

二分图最大匹配hopcroft-karp算法——HDU 2389的相关文章

hdu2389二分图之Hopcroft Karp算法

You're giving a party in the garden of your villa by the sea. The party is a huge success, and everyone is here. It's a warm, sunny evening, and a soothing wind sends fresh, salty air from the sea. The evening is progressing just as you had imagined.

hihoCoder #1122 : 二分图二?二分图最大匹配之匈牙利算法

#1122 : 二分图二•二分图最大匹配之匈牙利算法 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 上一回我们已经将所有有问题的相亲情况表剔除了,那么接下来要做的就是安排相亲了.因为过年时间并不是很长,所以姑姑希望能够尽可能在一天安排比较多的相亲.由于一个人同一天只能和一个人相亲,所以要从当前的相亲情况表里选择尽可能多的组合,且每个人不会出现两次.不知道有没有什么好办法,对于当前给定的相亲情况表,能够算出最多能同时

它处资料:二分图最大匹配的匈牙利算法

资料出处:点击打开链接 匈牙利算法 二分图最大匹配的匈牙利算法:  二分图是这样一个图,它的顶点能够分类两个集合X和Y,全部的边关联在两个顶点中.恰好一个属于集合X.还有一个属于集合Y. 最大匹配: 图中包括边数最多的匹配称为图的最大匹配. 完美匹配: 假设全部点都在匹配边上.称这个最大匹配是完美匹配. 最小覆盖: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和当中一个点关联.能够证明:最少的点(即覆盖数)=最大匹配数 最小路径覆盖: 用尽量少的不相交简单路径覆盖有向无环图G的全

HDU ACM 1281 棋盘游戏-&gt;二分图最大匹配(匈牙利算法实践)

分析:该題可以用x坐标去匹配y坐标,匹配成功一次就是一个可放棋子的点,最后求得的的二分图最大匹配就是可以放的最大棋子数.求二分图的最大匹配使用匈牙利算法.之后通过删除一条边来判断一个点是否为关键点,若删边后,最大匹配数不变则不是,否则是,通过分别删除每个点进行测试,最终即可算出关键点的个数. #include<iostream> using namespace std; #define N 102 int map[N][N]; //记录连接x和y的边 bool vis[N]; //记录y中节点

&quot;《算法导论》之‘图’&quot;:不带权二分图最大匹配(匈牙利算法)

博文“二分图的最大匹配.完美匹配和匈牙利算法”对二分图相关的几个概念讲的特别形象,特别容易理解.本文介绍部分主要摘自此博文. 还有其他可参考博文: 趣写算法系列之--匈牙利算法 用于二分图匹配的匈牙利算法 1. 前言 二分图:简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图.准确地说:把一个图的顶点划分为两个不相交集 U 和V ,使得每一条边都分别连接U.V中的顶点.如果存在这样的划分,则此图为一个二分图.二分图的一个等价定义是:不含有「含奇数条边的环」的图.

51nod 2006 飞行员配对(二分图最大匹配) 裸匈牙利算法 求二分图最大匹配题

题目: 题目已经说了是最大二分匹配题, 查了一下最大二分匹配题有两种解法, 匈牙利算法和网络流. 看了一下觉得匈牙利算法更好理解, 然后我照着小红书模板打了一遍就过了. 匈牙利算法:先试着把没用过的左边的点和没用过的右边的点连起来, 如果遇到一个点已经连过就试着把原来的拆掉 把现在这条线连起来看能不能多连上一条线. 总结来说就是试和拆,试的过程很简单,拆的过程由于使用递归写的,很复杂.很难讲清楚,只能看代码自己理会. 代码(有注释): #include <bits\stdc++.h> usin

POJ1469 COURSES 【二分图最大匹配&amp;#183;HK算法】

COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17777   Accepted: 7007 Description Consider a group of N students and P courses. Each student visits zero, one or more than one courses. Your task is to determine whether it is poss

算法练习系列—hiho1122二分图最大匹配之匈牙利算法

题目地址:http://hihocoder.com/problemset/problem/1122 该题目的关键是2个问题:1点用bfs构造二分图   2:针对二分图的其中S中的结点,遍历找增广路(匈牙利算法求二分图的最大匹配) 每找到一条增广路就多找到了一条匹配. 代码如下: /* 这题有两点需要注意:1点用bfs构造二分图 2:针对二分图的其中S中的结点,遍历找增广路(匈牙利算法求二分图的最大匹配) 每找到一条增广路 就多找到了一条匹配 */ #include <iostream> #in

二分图最大匹配(匈牙利算法)

首先是二分图定义与判断  http://www.cnblogs.com/wenruo/p/5243034.html 给定一个二分图G,M为G边集的一个子集,如果M满足当中的任意两条边都不连接同一个顶点,则称M是一个匹配. 一个很好的比喻是,一个二分图,左边代表男生,右边代表女生,连线代表有好感,匹配就是把他们互相有好感的撮合起来.当然,要一夫一妻! 所谓最大匹配,就是撮合最多对.(写下这句话的时候,我在图书馆,旁边有一对情侣在虐狗……) 完美匹配就是所有的人都不落单. 上图红线代表一个匹配,图中