hlg1481 Attack of the Giant n-pus【二分+二分图】

Attack of the Giant n-pus
Time Limit: 2000 MS Memory Limit: 65536 K
Total Submit: 71(6 users) Total Accepted: 8(5 users) Rating:  Special Judge: No
Description

A pirate ship is being attacked by a giant n-pus(hint 1) . The n tentacles and the head of the creature

have pierced the deck and are wreaking havoc on the ship. In an attempt to stop the creature

from completely destroying the ship, the captain charges towards the head of the creature. Un-

fortunately, he quickly gets knocked back by one of the tentacles. The captain realizes he cannot

attack the head of the n-pus as long as it can move its tentacles freely.

Luckily the captain is not alone on the ship. There are p (p ≥ n) pirates spread around on the

deck, ready to follow the captain’s orders. So the captain comes up with the following plan. If

each tentacle is attacked by one of the pirates, he can move freely towards the head of the creature

and ?nish it o?. To be safe, the captain will start moving only after each of the tentacles is being

attacked by a pirate. When the captain reaches the head, he can instantly kill the creature. The

captain wants to ?gure out which pirates to send to which tentacles, such that the creature can

be killed as fast as possible. As this happens regularly to pirates, the captain wants you to write

a program to solve this problem.

Input

The ?rst line of the input contains a single number: the number of test cases to follow. Each test

case has the following format:

• One line with two integers n and p, satisfying 1 ≤ n ≤ p ≤ 100: the number of tentacles of

the n-pus and the number of pirates (excluding the captain), respectively.

• One line with three integers xc , yc and vc : the captain’s coordinates and speed, respectively.

• p lines, each with three integers xi , yi and vi : the coordinates and speed, respectively, of

each pirate.

• One line with two integers xh and yh : the coordinates of the head of the n-pus.

• n lines, each with two integers xj and yj : the coordinates of each tentacle.

All coordinates satisfy 0 ≤ x, y ≤ 10, 000. All speeds satisfy 1 ≤ v ≤ 100.

The captain, the pirates, the head and the tentacles are all considered to be point-like (i.e. they

have no size). Their locations are all distinct.

The captain and all pirates move to their target in a straight line at their given speed and are not

hindered by anyone or anything.

Output

For every test case in the input, the output should contain one ?oating point number on a single

line: the minimum time it takes for the captain to kill the n-pus. Your answer should have either

an absolute or a relative error of at most 10^−6 .

Sample Input

3 3 
2 0 1 
0 0 2
1 0 3
3 0 4
2 3
0 1
1 1
4 1
1 3
0 0 1
3 0 1
4 0 1
7 0 2
0 1
4 2
3 3
0 0 2
2 0 3
3 0 1
4 0 2
0 1
3 1
4 1
5 1
Sample Output
3.500000000
2.802775638
1.500000000
Hint

1. An n-pus is like an octopus, but then with n tentacles.

原始题目的输出需要Special Judge,为了方便,输出答案时请精确到小数点后9位。

Source
BAPC 2011 Preliminaries

这个困扰我三天的题终于解开了啊

好艰辛啊

5555~~~

大意:

一群水手去攻击一只只爪子的章鱼

告诉你每个水手的位置和前进的速度

又告诉你每个章鱼爪子的位置

告诉你章鱼头部的位置又告诉你船长的位置和速度

船长只有在所有的爪子被水手控制的情况下才会去攻击章鱼的头部

问最后船长攻击到章鱼头部的最短时间

要求精度误差在0.000000001之内

分析:

二分枚举发动攻击的时间,如果在该时间内水手能够抵达一只爪子就建立一条边

最后求得结果

不得不去吐槽一下啊

黄老师不加sj还要求那么高的精度

简直就是丧心病狂啊

开始的时候一直TLE

然后发现一个可以大大提高时间的地方就是事先处理出每个水手到每只爪子的距离

然后还是TLE啊啊啊

然后看周洲的代码

发现他是用手写的邻接表

我想不能吧  这么丧心病狂

vector应该比邻接表慢不了几倍的速度吧

我就改成邻接表储存

结果

就a了

瞬间石化

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <vector>
  6 using namespace std;
  7
  8 const int maxn = 101;
  9
 10 int n, p;
 11
 12 struct Edge
 13 {
 14     int to,next;
 15 }e[10002];
 16 int head[maxn];
 17 int tot;
 18 void add(int s,int u)
 19 {
 20     e[tot].to = u;
 21     e[tot].next = head[s];
 22     head[s] = tot++;
 23 }
 24
 25 double xi[maxn], yi[maxn], vi[maxn];
 26 double xj[maxn], yj[maxn];
 27 double dist[maxn][maxn];
 28
 29 int vis[maxn], Link[maxn];
 30
 31 bool Find(int u) {
 32     for(int i = head[u]; i; i = e[i].next) {
 33         int v = e[i].to;
 34         if(!vis[v]) {
 35             vis[v] = 1;
 36             if(Link[v] == -1 || Find(Link[v]) ) {
 37                 Link[v] = u;
 38                 return true;
 39             }
 40         }
 41     }
 42     return false;
 43 }
 44
 45 bool Match() {
 46     memset(Link, -1, sizeof(Link));
 47     for(int i = 1; i <= n; i++) {
 48         memset(vis, 0, sizeof(vis));
 49         if(!Find(i) ) return false;
 50     }
 51     return true;
 52 }
 53
 54 double Dist(double x1, double y1, double x2, double y2) {
 55     double xx = x1 - x2;
 56     double yy = y1 - y2;
 57     return sqrt(xx * xx + yy * yy );
 58 }
 59
 60 bool check(double mid) {
 61     tot = 1; memset(head, 0, sizeof(head));
 62     for(int i = 1; i <= n; i++) {
 63         for(int j = 1; j <= p; j ++) {
 64             if(dist[i][j] < mid) {
 65                 add(i, j);
 66             }
 67         }
 68     }
 69     if(Match()) {
 70         return true;
 71     }
 72     return false;
 73 }
 74
 75 const double wucha = 0.0000000001;
 76
 77 int main() {
 78     double xc, yc, vc;
 79     double xh, yh;
 80     int t;
 81     //freopen("test.txt","r",stdin);
 82     scanf("%d",&t);
 83     while(t--) {
 84         scanf("%d %d",&n, &p);
 85         scanf("%lf %lf %lf", &xc, &yc, &vc);
 86         for(int i = 1;  i <= p; i++) {
 87             scanf("%lf %lf %lf", &xi[i], &yi[i], &vi[i]);
 88         }
 89         scanf("%lf %lf", &xh, &yh);
 90         for(int i = 1; i <= n; i++) {
 91             scanf("%lf %lf", &xj[i], &yj[i]);
 92         }
 93         double low = 0, high = 0;
 94         for(int i = 1;i <= n; i++) {
 95             for(int j = 1; j <= p; j++) {
 96                 dist[i][j] = Dist(xj[i], yj[i], xi[j], yi[j]) * 1.0 / vi[j];
 97                 if(dist[i][j] > high) high = dist[i][j];
 98             }
 99         }
100         while(low < high) {
101             double mid = (low + high) * 0.5;
102             if(!check(mid)) {
103                 low = mid + wucha;
104             } else {
105                 high = mid - wucha;
106             }
107         }
108         double ans = high + wucha;
109         ans += (Dist(xc, yc, xh, yh) / vc);
110         printf("%.9lf\n", ans);
111     }
112     return 0;
113 }

时间: 2024-08-14 21:50:10

hlg1481 Attack of the Giant n-pus【二分+二分图】的相关文章

Poj 2289 Jamie&#39;s Contact Groups (二分+二分图多重匹配)

题目链接: Poj 2289 Jamie's Contact Groups 题目描述: 给出n个人的名单和每个人可以被分到的组,问将n个人分到m个组内,并且人数最多的组人数要尽量少,问人数最多的组有多少人? 解题思路: 二分图多重匹配相对于二分匹配来说不再是节点间的一一对应,而是Xi可以对应多个Yi.所以我们就需要一个限制(Xi最多匹配几个Yi).当Yi需要匹配Xi的时候,Xi的匹配未到上限,直接匹配,否则进行增广路.其实是二分图多重匹配的模板题,再套一个二分枚举最多组的人数就OK咯.下面就上板

【bzoj4443】[Scoi2015]小凸玩矩阵 二分+二分图匹配

题目描述 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. 输入 第一行给出三个整数N,M,K 接下来N行,每行M个数字,用来描述这个矩阵 输出 如题 样例输入 3 4 2 1 5 6 6 8 3 4 3 6 8 6 3 样例输出 3 题解 二分+二分图最大匹配 最(第k)大值最小,很容易想到二分答案. 二分一个mid,若满足条件,一定满足:可以选出n-k+1个不

SPOJ AMR12A The Black Riders --二分+二分图最大匹配

题意:有n个人,m个洞.每个洞能容纳一个人,每个人到每个洞需要花费一些时间.每个人到达一个洞后可以花C的时间来挖一个洞,并且最多挖一个洞,这样又能多容纳一人.求能使至少K个人进洞的最短时间. 解法:看到n个人和m个洞,并且人要进洞容易想到二分匹配,又是求极值的问题,应该是最大匹配.由于直接求极值不好求,可以将求极值问题转化为判定问题,即二分最短时间,然后判定能否达到.判定时,如果i到j的时间小于等于mid,就将i和j连一条边,如果T[i][j]+C <= mid 说明还来得及挖洞,将i和j+m连

HDU1669 Jamie&#39;s Contact Groups (二分+二分图的多重匹配)

多重匹配:一对多的二分图的多重匹配.二分图的多重匹配算法的实现类似于匈牙利算法,对于集合X中的元素xi,找到一个与其相连的元素yi后,检查匈牙利算法的两个条件是否成立,若yi未被匹配,则将 xi,yi匹配.否则,如果与yi匹配的元素已经达到上限,那么在所有与yi匹配的元素中选择一个元素,检查是否能找到一条增广路径,如果能,则让出位置,让xi与yi匹配. match[i][j]表示X集合中的Xi点与y集合中的j个点相连接(一对多) #include<cstdio> #include<ios

POJ2289:Jamie&#39;s Contact Groups(二分+二分图多重匹配)

Jamie's Contact Groups Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others) 题目链接:http://poj.org/problem?id=2289 Description: Jamie is a very popular girl and has quite a lot of friends, so she always keeps a very long

zoj 3460 二分+二分图匹配

不错的思想 1 /* 2 大致题意: 3 4 用n个导弹发射塔攻击m个目标.每个发射架在某个时刻只能为 5 一颗导弹服务,发射一颗导弹需要准备t1的时间,一颗导弹从发 6 射到击中目标的时间与目标到发射架的距离有关.每颗导弹发 7 射完成之后发射架需要t2的时间进入下个发射流程.现在问 8 最少需要多少时间可以击毁所有m个目标. 9 10 11 大致思路: 12 二分枚举这个最大时间的最小值,每次按照这个枚举的时间构出 13 二分图,求最大匹配来判定枚举值是否符合要求. 14 15 注意单位,T

[NOIP2010]关押罪犯(二分+二分图染色)

传送门 大意:我们把图分为两部分,使得两部分中的内部边的最大权值最小. 思路:哎,拿到题的时候想了二分图染色,发现不好做,但我没有想到二分,只好最后去骗了一个30分.正确的思路是:首先我们要 去二分最大的冲突边的是哪一条(按照权值二分),因为当二分的边权增大时,连的边也就越少,连通块的数目就越多,冲突就越少,所以边权是可以二分的,在二分过后用二分图判定,如果可以染成二分图即为可行的解. 代码: #include<cstdio> #include<algorithm> #includ

【BZOJ4443】[Scoi2015]小凸玩矩阵 二分+二分图最大匹配

[BZOJ4443][Scoi2015]小凸玩矩阵 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N行,每行M个数字,用来描述这个矩阵 Output 如题 Sample Input 3 4 2 1 5 6 6 8 3 4 3 6 8 6 3 Sample Output 3 HINT 1<

ZOJ 3460 Missile(二分+ 二分图匹配)

解题思路: 把每一个可发射导弹的时间看成一个发射装置,总共n * m个,然后二分答案 #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <string.h> #include <vector> #include <queue> #include <mat