HDU-2389-Rain on your Parade [二分匹配][Hopcroft-Carp]


題目傳送門


題意:有n個人的座標和速度,有m個傘的座標,問有多少人能在t秒內到傘底下,一個傘底下只能有一個人。

思路:二分匹配,用匈牙利算法無限超時,又改用鄰接表還是超時,最後查資料才知道處理數據較大的二分匹配需要用Hopcroft-Carp算法。

Hopcroft-Carp算法模板:

/* *********************************************
二分圖匹配(Hopcroft-Carp的算法)。
初始化:g[][]鄰接矩陣
調用:res=MaxMatch();  Nx,Ny要初始化!!!
時間複雜大爲 O(V^0.5 E)

適用於數據較大的二分匹配
需要queue頭文件
********************************************** */
const int MAXN=3100;
const int INF=0x3f3f3f3f;
int g[MAXN][MAXN],Mx[MAXN],My[MAXN],Nx,Ny;
int dx[MAXN],dy[MAXN],dis;
bool vst[MAXN];
bool searchP()
{
    queue<int>Q;
    dis=INF;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(int i=0;i<Nx;i++)
        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 v=0;v<Ny;v++)
            if(g[u][v]&&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!=INF;
}
bool DFS(int u)
{
    for(int v=0;v<Ny;v++)
       if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1)
       {
           vst[v]=1;
           if(My[v]!=-1&&dy[v]==dis) continue;
           if(My[v]==-1||DFS(My[v]))
           {
               My[v]=u;
               Mx[u]=v;
               return 1;
           }
       }
    return 0;
}
int MaxMatch()
{
    int res=0;
    memset(Mx,-1,sizeof(Mx));
    memset(My,-1,sizeof(My));
    while(searchP())
    {
        memset(vst,0,sizeof(vst));
        for(int i=0;i<Nx;i++)
            if(Mx[i]==-1&&DFS(i))  
            res++;
    }
    return res;
}
//**************************************************************************/

題解:

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>

using namespace std;

/* *********************************************
二分圖匹配(Hopcroft-Carp的算法)。
初始化:g[][]鄰接矩陣
調用:res=MaxMatch();  Nx,Ny要初始化!!!
時間複雜大爲 O(V^0.5 E)

適用於數據較大的二分匹配
需要queue頭文件
********************************************** */
const int MAXN=3100;
const int INF=0x3f3f3f3f;
int g[MAXN][MAXN],Mx[MAXN],My[MAXN],Nx,Ny;
int dx[MAXN],dy[MAXN],dis;
bool vst[MAXN];
bool searchP()
{
    queue<int>Q;
    dis=INF;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(int i=0;i<Nx;i++)
        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 v=0;v<Ny;v++)
            if(g[u][v]&&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!=INF;
}
bool DFS(int u)
{
    for(int v=0;v<Ny;v++)
       if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1)
       {
           vst[v]=1;
           if(My[v]!=-1&&dy[v]==dis) continue;
           if(My[v]==-1||DFS(My[v]))
           {
               My[v]=u;
               Mx[u]=v;
               return 1;
           }
       }
    return 0;
}
int MaxMatch()
{
    int res=0;
    memset(Mx,-1,sizeof(Mx));
    memset(My,-1,sizeof(My));
    while(searchP())
    {
        memset(vst,0,sizeof(vst));
        for(int i=0;i<Nx;i++)
            if(Mx[i]==-1&&DFS(i))  
            res++;
    }
    return res;
}
//**************************************************************************/
int t;
struct node{
    int x, y, s;
}peo[MAXN];
struct node1{
    int x,y;
}ubl[MAXN];
int Dis(node a, node1 b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int main(void)
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

    int T, cas=1;
    scanf("%d", &T);
    while(T--)
    {
        int n,m;
        memset(g, 0, sizeof(g));
        scanf("%d", &t);
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
            scanf("%d %d %d", &peo[i].x, &peo[i].y, &peo[i].s);
        scanf("%d", &m);
        for (int i = 0; i < m; i++)
            scanf("%d %d", &ubl[i].x, &ubl[i].y);
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                if (Dis(peo[i], ubl[j])<=peo[i].s*peo[i].s*t*t)
                    g[i][j]=1;
        Nx = n;
        Ny = m;
        printf("Scenario #%d:\n%d\n\n", cas++, MaxMatch());
    }
    return 0;
}
發佈了101 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章