zoukankan      html  css  js  c++  java
  • hdu 2389 Rain on your Parade (Hopcroft-Karp 求二分图最大匹配)

    • 题意: 给出m个点和n个人,每个人有一个速度,可以跑向一个点,但每个点只能被一个人占领
    • 思路: 每个人和每个点都建一个点,如果人能跑到点则连一条边,求最大匹配即可.
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int INF = 0x3f3f3f3f;
    
    const int N = 3050;
    int uN,vN,t;
    
    struct point{
        int x,y;
         point(){}
         point(int x,int y):x(x),y(y){}
    };
    
    point a[N],b[N];
    int vor[N];
    int Mx[N],My[N];
    // Mx 表示左集合顶点所匹配的右集合顶点序号, My 相反
    int dx[N],dy[N];
    // dx 表示左集合i顶点距离编号 dy 为右集合
    int used[N];
    int dis;
    vector<int> g[N];
     // 寻找增广路径集,每次只寻找当前最短的增广路
    bool SearchP(){
        queue<int> Q;
        dis = INF;
        memset(dy,-1,sizeof dy);
        memset(dx,-1,sizeof dx);
        for(int i=1;i<=uN;++i){
            if(Mx[i] == -1){    //将未匹配的节点入队,并初始化其距离为0
                Q.push(i);
                dx[i] = 0;
            }
        }
        while(!Q.empty()){
            int u = Q.front();
            Q.pop();
            if(dx[u] > dis) break;
            int sz = g[u].size();
            for(int i=0;i<sz ;++i){
                int v = g[u][i];
                if(dy[v] == -1){
                    dy[v] = dx[u] +1;
                    if(My[v] == -1) dis = dy[v];    // 找到了一条增广路,dis为增广路终点的编号
                    else{
                        dx[My[v]] = dy[v]+1;
                        Q.push(My[v]);
                    }
                }
            }
        }
        return dis!=INF;
    }
    bool DFS(int u){
        int sz = g[u].size();
        for(int i=0;i<sz;++i){
            int v = g[u][i];
            if(!used[v] && dy[v] == dx[u]+1){   // 当前节点没有匹配,且距离上一节点+1
                used[v] = true;
                if(My[v] != -1 && dy[v]==dis)   continue;   // v已经被匹配且已到所有存在的增广路终点的编号,不可能存在增广路
                if(My[v] == -1 || DFS(My[v])){
                    My[v] = u;
                    Mx[u] = v;
                    return true;
                }
            }
        }
        return false;
    }
    int MaxMatch(){
        int res = 0;
        memset(Mx,-1,sizeof Mx);
        memset(My,-1,sizeof My);
        while(SearchP()){
            memset(used,0,sizeof used);
            for(int i=1;i<=uN;++i){
                if(Mx[i]==-1 && DFS(i)){
                    res++;
                }
            }
        }
        return res;
    }
    
    int check(int u,int v){
        double dis = (a[u].x - b[v].x)*(a[u].x - b[v].x)*1.0 +1.0*(a[u].y-b[v].y)*(a[u].y-b[v].y);
        double len = vor[u]*t*t*vor[u];
        return len >= dis;
    }
    
    void solve(){
        memset(g,0,sizeof g);
        scanf("%d%d",&t,&uN);
        for(int i=1;i<=uN;++i){
            scanf("%d%d%d",&a[i].x,&a[i].y,&vor[i]);
        }
        scanf("%d",&vN);
        for(int i=1;i<=vN;++i){
            scanf("%d%d",&b[i].x,&b[i].y);
        }
    
        for(int i=1;i<=uN;++i){
            for(int j=1;j<=vN;++j){
                if(check(i,j)){
                    g[i].push_back(j);
                }
            }
        }    
        printf("%d
    ",MaxMatch());
    }
    
    int main(){
        int t;
        scanf("%d",&t);
        for(int i=1;i<=t;i++){
            printf("Scenario #%d:
    ",i);
            solve();
            puts("");
        }
        return 0;
    }
    
  • 相关阅读:
    Python JSON的基本使用
    python socket函数详解
    python关于字符编码的基本操作
    关于git的一些简单命令
    CS和BS结构的优缺点
    Web测试详细点
    详解SESSION与COOKIE的区别
    如何测试一个网页登陆界面
    二层交换机、三层交换机和路由器的原理及区别
    LSA分类
  • 原文地址:https://www.cnblogs.com/xxrlz/p/11391563.html
Copyright © 2011-2022 走看看