UVA 10080 Gopher II【简单二部图最大匹配】

题目大意:给出田鼠数目与地洞数目,每个地洞可以容纳一只田鼠,给出田鼠坐标与地洞坐标,田鼠速度与逃逸最大时间,求出最少被抓住田鼠数。

解题策略:简单二部图,答案 = 田鼠总数-(田鼠——地洞)二部图最大匹配数,邻接表实现。



/*
   UVA 10080 Gopher II
   AC by J_Dark
   ON 2013/4/19
   Time 0.044s
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
int gopherNum, holesNum, timeLimit, speed, ans;
struct XY{  
   double x, y;
   XY(double a=0, double b=0) { x = a; y = b;}
   double pathCompute(XY A){
      return sqrt(pow(A.x-x, 2.0) + pow(A.y-y, 2.0));
   }   
};
vector< vector<int> > reachedHoles;  
vector<XY> G;  //田鼠 
vector<XY> H;  //地洞 
vector<int> pairHG; //存放匹配边 
vector<bool> visited;  //增广路径判定标记

//寻找增光路径 
bool findPath(int g){
   for(int i=0; i<reachedHoles[g].size(); i++){
      int tempH = reachedHoles[g][i];
      if(!visited[tempH]){
         visited[tempH] = true;
         if( pairHG[tempH] == -1 || findPath(pairHG[tempH]) ){ //发现未匹配边
            pairHG[tempH] = g; //修改匹配信息 
            return true;
         }
      } 
   }
   return false; //未找到匹配边 
} 
//匈牙利算法 DFS求最大匹配
void Compute(){
     int matching = 0;
     for(int g=0; g<gopherNum; g++){
        visited.clear();
        visited.resize(holesNum);
        if(findPath(g))
           matching++;
     }
	 //最少被抓住田鼠数 = 田鼠总数 - 最大匹配数
     cout << gopherNum - matching << endl;
}


void Input(){
     double x, y;
     G.clear();
     H.clear();
     for(int i=0; i<gopherNum; i++){
        cin >> x >> y;
        G.push_back(XY(x, y));
     }
     for(int i=0; i<holesNum; i++){
        cin >> x >> y;
        H.push_back(XY(x, y));
     }   
     reachedHoles.clear();
     pairHG.clear();
     for(int h=0; h<holesNum; h++)  pairHG.push_back(-1); //初始化未匹配 
}

void Solve(){
     const double eps = 1e-10;
     vector<int> holes;
     for(int g=0; g<G.size(); g++){
         holes.clear();
         for(int h=0; h<H.size(); h++){
            if(double(timeLimit*speed) - G[g].pathCompute(H[h]) > eps)
               holes.push_back(h);
         }
         reachedHoles.push_back(holes);
     }
}
/
int main(){
 
    while(cin >> gopherNum >> holesNum >> timeLimit >> speed)
    {
       Input();
       Solve();
       Compute();
    }
    //system("pause");
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值