博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 2389 Rain on your Parade / HUST 1164 4 Rain on your Parade(二分图的最大匹配)
阅读量:4673 次
发布时间:2019-06-09

本文共 6789 字,大约阅读时间需要 22 分钟。

HDU 2389 Rain on your Parade / HUST 1164 4 Rain on your Parade(二分图的最大匹配)

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

Http

HDU:

HUSTT:

Source

二分图的最大匹配

题目大意

现在马上要下雨了,给出n个人和m把雨伞的坐标位置,以及每个人的奔跑速度,还有距离下雨的时间。每把雨伞只能供一人使用。求在下雨前最多有多少人可以拿到雨伞。

解决思路

这个题目一看就是二分图的最大匹配问题。但若直接把匈牙利算法往上一摆,会TLE。

为什么呢?好好看题:n,m<=3000。而原来我们做的题目都是n,m<=100或<=200的。所以这道题不能直接用匈牙利算法解决。

所以这道题我们要用到匈牙利算法的改进版:Hopcroft-Karp算法(一下简称HK算法)

我们知道,匈牙利算法时间效率不高的原因就是在一次匹配时只走一条增广边,每次都要重新找增广边,所以时间效率低。

那么,HK算法就是在每一次判断前,先用一个bfs预处理处理出多条增广边,下面先给出代码。

代码中的变量说明:

Dist:一个全局变量,保存当前最长的增广路的深度,方便及时退出bfs,同时也方便后面再进行Hungary时及时退出(后面会讲到)
Deep_x:人对应的点的深度(也就是到此点时的增广路长度),同时可以方便判断人i是否在这次bfs中走过了。这个变量在匈牙利算法中也会用到(后面会说到)
Deep_y:伞对应的点的深度(同上),也能判断伞是否在这次bfs中是否用过
Match_x:人所匹配的伞的编号
Match_y:伞所匹配的人的编号
E:从人->伞的边
其他变量的意义与题目一致

bool bfs(){    queue
Q;//bfs要用的队列 while (!Q.empty()) Q.pop(); Dist=inf;//先置为inf mem(Deep_x,-1);//先置为-1,表示还未经过 mem(Deep_y,-1); for (int i=1;i<=m;i++) if (Match_x[i]==-1)//若人i还未匹配,则将其加入队列(因为增广路的开始点是未匹配点) { Deep_x[i]=0; Q.push(i); } while (!Q.empty())//因为有可能所有人都已经匹配,所以要把while判断写前面,以免出现RE { int u=Q.front(); Q.pop(); if (Deep_x[u]>Dist)//若发现当前选出的人u的深度已经大于能形成增广路的最大深度了,直接退出。这是一个很好的剪枝 break; for (int i=0;i

总计一下,这个bfs过程的意义就是增广多条增广路,方便后面匈牙利算法。

那么接下来就是修改匈牙利算法了。还是先给出代码。

bool Hungary(int u){    for (int i=0;i

最后总计一下HK算法的主要流程就是:

先找出多条不相交的增广路。
用匈牙利算法进行匹配。

(如有不正确之处还请各路神犇指教)

代码(后面附上了TLE的纯匈牙利算法)

#include
#include
#include
#include
#include
#include
#include
using namespace std;#define ll long long#define mem(Arr,x) memset(Arr,x,sizeof(Arr))const int maxN=4000;const int inf=2147483647;int n,m;int Time;//距离下雨的时间int Dist;//下面这些变量的意义在上文已经讲过啦vector
E[maxN];int Match_x[maxN];int Match_y[maxN];bool vis[maxN];int Deep_x[maxN];int Deep_y[maxN];int X[maxN];//人的X坐标int Y[maxN];int Speed[maxN];//人的速度int read();bool Judge(int u,int v,int num);bool bfs();bool Hungary(int u);int main(){ int T; T=read(); for (int ti=1;ti<=T;ti++) { Time=read(); m=read(); for (int i=1;i<=m;i++) E[i].clear(); for (int i=1;i<=m;i++) { X[i]=read(); Y[i]=read(); Speed[i]=read(); } n=read(); for (int i=1;i<=n;i++) { int x,y; x=read(); y=read(); for (int j=1;j<=m;j++) if (Judge(x,y,j)) { E[j].push_back(i); } } int Ans=0; mem(Match_x,-1); mem(Match_y,-1); while (bfs())//HK算法 { mem(vis,0); for (int i=1;i<=m;i++) if (Match_x[i]==-1) if (Hungary(i)) Ans++; } printf("Scenario #%d:\n%d\n\n",ti,Ans); } return 0;}int read()//读入优化{ int x=0; int k=1; char ch=getchar(); while (((ch<'0')||(ch>'9'))&&(ch!='-')) ch=getchar(); if (ch=='-') { k=-1; ch=getchar(); } while ((ch<='9')&&(ch>='0')) { x=x*10+ch-48; ch=getchar(); } return x*k;}bool Judge(int u,int v,int num)//判断某个人是否可以跑到某把伞{ long long Dist=(long long)((X[num]-u))*(X[num]-u)+(long long)((Y[num]-v))*(Y[num]-v); long long D=(long long)(Time)*Speed[num]; if (D*D>=Dist) return 1; return 0;}bool bfs(){ queue
Q;//bfs要用的队列 while (!Q.empty()) Q.pop(); Dist=inf;//先置为inf mem(Deep_x,-1);//先置为-1,表示还未经过 mem(Deep_y,-1); for (int i=1;i<=m;i++) if (Match_x[i]==-1)//若人i还未匹配,则将其加入队列(因为增广路的开始点是未匹配点) { Deep_x[i]=0; Q.push(i); } while (!Q.empty())//因为有可能所有人都已经匹配,所以要把while判断写前面,以免出现RE { int u=Q.front(); Q.pop(); if (Deep_x[u]>Dist)//若发现当前选出的人u的深度已经大于能形成增广路的最大深度了,直接退出。这是一个很好的剪枝 break; for (int i=0;i
#include
#include
#include
#include
#include
using namespace std;const int maxN=4000;const int inf=2147483647;int n,m;vector
E[maxN];bool vis[maxN];int Match[maxN];int GuestX[maxN];int GuestY[maxN];int Speed[maxN];int read();bool Hungary(int u);int main(){ int T; int Time; cin>>T; for (int ti=1;ti<=T;ti++) { cin>>Time; cin>>m; for (int i=1;i<=m;i++) E[i].clear(); for (int i=1;i<=m;i++) { GuestX[i]=read(); GuestY[i]=read(); Speed[i]=read(); Speed[i]=Speed[i]*Time; } int x,y; cin>>n; for (int i=1;i<=n;i++) { x=read(); y=read(); for (int j=1;j<=m;j++) { int Dist=(x-GuestX[j])*(x-GuestX[j])+(y-GuestY[j])*(y-GuestY[j]); if (Speed[i]*Speed[i]>=Dist) E[j].push_back(i); } } int Ans=0; memset(Match,-1,sizeof(Match)); for (int i=1;i<=m;i++) { memset(vis,0,sizeof(vis)); if (Hungary(i)) { Ans++; } } printf("Scenario #%d:\n%d\n\n",ti,Ans); //cout<
<
'9'))&&(ch!='-')) ch=getchar(); if (ch=='-') { k=-1; ch=getchar(); } while ((ch<='9')&&(ch>='0')) { x=x*10+ch-48; ch=getchar(); } return x*k;}bool Hungary(int u){ for (int i=0;i

转载于:https://www.cnblogs.com/SYCstudio/p/7138258.html

你可能感兴趣的文章
单元测试之初识
查看>>
golang github.com/go-sql-driver/mysql 遇到的数据库,设置库设计不合理的解决方法
查看>>
内存分配 保存数据
查看>>
磁盘分区、格式化
查看>>
嵌入式实时操作系统的可裁剪性及其实现
查看>>
VC++2012编程演练数据结构《31》狄杰斯特拉算法
查看>>
盘点:移动服务 #AzureChat
查看>>
基于visual Studio2013解决C语言竞赛题之0608水仙花函数
查看>>
Sass学习笔记
查看>>
C语言练习
查看>>
Eclipse:An internal error occurred during: "Building workspace". GC overhead limit exceeded
查看>>
纯Css实现Div高度根据自适应宽度(百分比)调整
查看>>
jboss eap6.1(4)(部署应用)
查看>>
配置jboss EAP 6.4 数据库连接超时时间
查看>>
【BZOJ5005】乒乓游戏 [线段树][并查集]
查看>>
前端页面数据埋点、分析和参考
查看>>
NBear简介与使用图解
查看>>
ng-app一些使用
查看>>
ubuntu16.04安装 java JDK8
查看>>
中兴F412光猫超级密码破解、破解用户限制、关闭远程控制、恢复路由器拨号
查看>>