zoukankan      html  css  js  c++  java
  • Hdu 3289 Rain on your Parade (二分图匹配 Hopcroft-Karp)

    题目链接:

      Hdu 3289 Rain on your Parade

    题目描述:
      有n个客人,m把雨伞,在t秒之后将会下雨,给出每个客人的坐标和每秒行走的距离,以及雨伞的位置,问t秒后最多有几个客人可以拿到雨伞?

    解题思路:

      数据范围太大,匈牙利算法O(n*m)果断华丽丽的TLE,请教了一下度娘,发现还有一种神算法—— Hopcroft-Karp,然后就get√新技能,一路小跑过了,有一点不明白的是hdu上竟然有人0ms过,这又是什么神姿势(吓哭!!!!!),额.........,扯远了

       Hopcroft-Karp复杂度O(sqrt(n)*m),相比匈牙利算法优化在于,Hopcroft-Karp算法每次可以扩展多条不相交增广路径。

      1 #include <iostream>
      2 #include <cstring>
      3 #include <queue>
      4 #include <cmath>
      5 #include <cstdio>
      6 using namespace std;
      7 
      8 const int maxn = 3000;
      9 const int INF = 0x3f3f3f3f;
     10 struct node
     11 {
     12     int to, next;
     13 } edge[maxn*maxn+10];
     14 struct point
     15 {
     16     double x, y, num;
     17 };
     18 point p_gue[maxn+5], p_umb[maxn+5];
     19 int head[maxn+5], vis[maxn+5], n, m, tot, dis;
     20 int cx[maxn+5], cy[maxn+5], dx[maxn+5], dy[maxn+5];
     21 
     22 void Add (int from, int to)
     23 {
     24     edge[tot].to = to;
     25     edge[tot].next = head[from];
     26     head[from] = tot ++;
     27 }
     28 
     29 bool bfs ()
     30 {//寻找多条无公共点的最短增广路
     31     queue <int> Q;
     32     dis = INF;
     33     memset (dx, -1, sizeof(dx));
     34     //左边顶点i所在层编号
     35     memset (dy, -1, sizeof(dy));
     36     //右边顶点i所在层编号
     37     for (int i=1; i<=n; i++)
     38         if (cx[i] == -1)
     39         {
     40             Q.push(i);
     41             dx[i] = 0;
     42         }
     43     while (!Q.empty())
     44     {
     45         int u = Q.front();
     46         Q.pop();
     47         if (dx[u] > dis)
     48             break;
     49         for (int i=head[u]; i!=-1; i=edge[i].next)
     50         {
     51             int v = edge[i].to;
     52             if (dy[v] == -1)
     53             {
     54                 dy[v] = dx[u] + 1;
     55                 if (cy[v] == -1)
     56                     dis = dy[v];
     57                 else
     58                 {
     59                     dx[cy[v]] = dy[v] + 1;
     60                     Q.push(cy[v]);
     61                 }
     62             }
     63         }
     64     }
     65     return dis != INF;
     66 }
     67 int dfs (int u)
     68 {//寻找路径
     69     for (int i=head[u]; i!=-1; i=edge[i].next)
     70     {
     71         int v = edge[i].to;
     72         if (!vis[v] && dy[v] == dx[u]+1)
     73         {
     74             vis[v] = 1;
     75             if (cy[v]!=-1 && dis==dy[v])
     76                 continue;
     77             if (cy[v]==-1 || dfs(cy[v]))
     78             {
     79                 cy[v] = u;
     80                 cx[u] = v;
     81                 return 1;
     82             }
     83         }
     84     }
     85     return 0;
     86 }
     87 int Max_match ()
     88 {//得到最大匹配数目
     89     int res = 0;
     90     memset (cx, -1, sizeof(cx));
     91     //左边顶点i所匹配的右边的点
     92     memset (cy, -1, sizeof(cy));
     93     //右边顶点i所匹配的左边的点
     94     while (bfs ())
     95     {
     96         memset (vis, 0, sizeof(vis));
     97         for (int i=1; i<=n; i++)
     98             if (cx[i] == -1)
     99                 res += dfs(i);
    100     }
    101     return res;
    102 }
    103 int main ()
    104 {
    105     int cas, t, l = 0;
    106     scanf ("%d", &cas);
    107     while (cas --)
    108     {
    109         scanf ("%d %d", &t, &n);
    110         for (int i=1; i<=n; i++)
    111         {
    112             scanf ("%lf %lf %lf", &p_gue[i].x, &p_gue[i].y, &p_gue[i].num);
    113             p_gue[i].num *= t;
    114         }
    115 
    116         scanf ("%d", &m);
    117         for (int i=1; i<=m; i++)
    118             scanf ("%lf %lf", &p_umb[i].x, &p_umb[i].y);
    119 
    120         memset (head, -1, sizeof(head));
    121         tot = 0;
    122         for (int i=1; i<=n; i++)
    123             for (int j=1; j<=m; j++)
    124             {
    125                 double x = p_gue[i].x - p_umb[j].x;
    126                 double y = p_gue[i].y - p_umb[j].y;
    127                 double num = sqrt (x*x + y*y);
    128                 if (num <= p_gue[i].num)
    129                     Add (i, j);
    130             }
    131         printf ("Scenario #%d:
    %d
    
    ", ++l, Max_match());
    132     }
    133     return 0;
    134 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    javascript:;与javascript:void(0);
    visual studio 扩展插件
    大数据大规律
    由浅入深理解express源码(四)
    由浅入深理解express源码(三)
    由浅入深理解express源码(二)
    由浅入深理解express源码(一)
    mac链接linux终端,shell脚本发布代码
    Mac nginx 配置
    js正则表达式之解析——URL的正则表达式
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4700393.html
Copyright © 2011-2022 走看看