二分图(H-K算法)

Problem 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 <= si <= 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

题意:找出人和伞之间的关系就得n^2的时间,匈牙利算法果断超时。

H-K算法复杂度o(sqrt(n)E).

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
typedef long long LL;
typedef pair<int,int>pil;
const int maxn=3000+100;
int head[maxn];
int mx[maxn],my[maxn];
int dx[maxn],dy[maxn];
int used[maxn];
struct Node{
   int x,y;
   int  s;
}e[maxn];
struct node{
   int x,y;
}pos[maxn];
struct edge{
    int u,v;
    int next;
}ee[maxn*maxn];
int cas,t,n,m,cnt,num,dis;
bool SearchP()
{
    queue<int>q;
    dis=0x3f3f3f3f;
    CLEAR(dx,-1);
    CLEAR(dy,-1);
    REPF(i,1,n)
      if(mx[i]==-1)
      {
          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=ee[i].next)
        {
            int v=ee[i].v;
            if(dy[v]==-1)
            {
                dy[v]=dx[u]+1;
                if(my[v]==-1)  dis=dy[v];
                else
                {
                    dx[my[v]]=dy[v]+1;
                    q.push(my[v]);
                }
            }
        }
    }
    return dis!=0x3f3f3f3f;
}
bool dfs(int u)
{
    for(int i=head[u];i!=-1;i=ee[i].next)
    {
        int v=ee[i].v;
        if(!used[v]&&dy[v]==dx[u]+1)
        {
            used[v]=1;
            if(my[v]!=-1&&dy[v]==dis)  continue;
            if(my[v]==-1||dfs(my[v]))
            {
                my[v]=u;
                mx[u]=v;
                return true;
            }
        }
    }
    return  false;
}
void work()
{
    int res=0;
    CLEAR(mx,-1);
    CLEAR(my,-1);
    while(SearchP())
    {
        CLEAR(used,0);
        REPF(i,1,n)
          if(mx[i]==-1&&dfs(i))  res++;
    }
    printf("Scenario #%d:\n%d\n\n",++num,res);
}
bool ok(int i,int j)
{
    double d=sqrt((double)(e[i].x-pos[j].x)*(e[i].x-pos[j].x)+(double)(e[i].y-pos[j].y)*(e[i].y-pos[j].y));
    return d/e[i].s<=t;
}
void addedge(int u,int v)
{
    ee[cnt].u=u;ee[cnt].v=v;
    ee[cnt].next=head[u];
    head[u]=cnt++;
}
int main()
{
    int x,y,w;
    num=0;
    scanf("%d",&cas);
    while(cas--)
    {
        CLEAR(head,-1);cnt=0;
        scanf("%d%d",&t,&n);
        REPF(i,1,n)
            scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].s);
        scanf("%d",&m);
        REPF(i,1,m)
        {
            scanf("%d%d",&pos[i].x,&pos[i].y);
            REPF(j,1,n)
                if(ok(j,i))  addedge(j,i);
        }
        work();
    }
    return 0;
}
时间: 2025-01-02 17:25:49

二分图(H-K算法)的相关文章

POJ1274 The Perfect Stall 二分图,匈牙利算法

N头牛,M个畜栏,每头牛只喜欢其中的某几个畜栏,但是一个畜栏只能有一只牛拥有,问最多可以有多少只牛拥有畜栏. 典型的指派型问题,用二分图匹配来做,求最大二分图匹配可以用最大流算法,也可以用匈牙利算法,这里使用匈牙利算法. #include <stdlib.h> #include <stdio.h> #include <vector> #include <math.h> #include <string.h> #include <string

过山车(二分图_匈牙利算法)

Description RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了.可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐.但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner.考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿

HDU 5943 Kingdom of Obsession 【二分图匹配 匈牙利算法】 (2016年中国大学生程序设计竞赛(杭州))

Kingdom of Obsession Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 49    Accepted Submission(s): 14 Problem Description There is a kindom of obsession, so people in this kingdom do things very

Ural1109_Conference(二分图最大匹配/匈牙利算法/网络最大流)

解题报告 二分图第一题. 题目描述: 为了参加即将召开的会议,A国派出M位代表,B国派出N位代表,(N,M<=1000) 会议召开前,选出K队代表,每对代表必须一个是A国的,一个是B国的; 要求每一个代表要与另一方的一个代表联系,除了可以直接联系,也可以电话联系,求电话联系最少 思路: 电话联系最少就要使直接联系最大,又是一一匹配关系,就是二分图的最大匹配. 下面是匈牙利算法. #include <cstdio> #include <cstring> #include <

UESTC 919 SOUND OF DESTINY --二分图最大匹配+匈牙利算法

二分图最大匹配的匈牙利算法模板题. 由题目易知,需求二分图的最大匹配数,采取匈牙利算法,并采用邻接表来存储边,用邻接矩阵会超时,因为邻接表复杂度O(nm),而邻接矩阵最坏情况下复杂度可达O(n^3). 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> u

HDU1507 Uncle Tom&#39;s Inherited Land* 二分图匹配 匈牙利算法 黑白染色

原文链接http://www.cnblogs.com/zhouzhendong/p/8254062.html 题目传送门 - HDU1507 题意概括 有一个n*m的棋盘,有些点是废的. 现在让你用1*2的矩形覆盖所有的不废的点,并且不重叠,问最多可以覆盖多少个1*2的矩形,输出方案,有SPJ. 输入描述: 多组数据,每组首先两个数n,m(如果n和m为0,则结束程序) 然后给出k 然后给出k个二元组(x,y)表示废点的坐标. 题解 按照前两片博文的算法已经不行了,因为方案不对了. 所以我们要进行

训练指南 UVALive - 4043(二分图匹配 + KM算法)

layout: post title: 训练指南 UVALive - 4043(二分图匹配 + KM算法) author: "luowentaoaa" catalog: true mathjax: true tags: - 二分图匹配 - 图论 - 训练指南 Ants UVALive - 4043 题意 给你n个白点和n个黑点的平面坐标,要求用n条不相交的线连起来,每条线段连一个白点和黑点,每个点连一条线,也就是匹配.让你输出第i个白点所对应的黑点. 思路 二分图完美匹配问题.但是题目

POJ1274:The Perfect Stall(二分图最大匹配 匈牙利算法)

The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17895   Accepted: 8143 Description Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering pr

USACO 4.2 The Perfect Stall(二分图匹配匈牙利算法)

The Perfect StallHal Burch Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering problems, all the stalls in the new barn are different. For the first week, Farmer John r

SPOJ 4206 Fast Maximum Matching (二分图最大匹配 Hopcroft-Carp 算法 模板)

题目大意: 有n1头公牛和n2头母牛,给出公母之间的m对配对关系,求最大匹配数.数据范围:  1 <= n1, n2 <= 50000, m <= 150000 算法讨论: 第一反应KM直接上,第二反应,KM是O(N^2 * M)的,会T成狗. 第二反应,看看大家是怎么做的.后来发现了一个名字叫 Hopcroft-Carp的二分图最大匹配的算法.可以在O(sqrt(n) * m)的时间内解决二分图的最大匹配问题.非常适合大数据的二分图匹配.所以就学习了一下. 我们知道,普通的匈牙利慢的原