zoukankan      html  css  js  c++  java
  • hdu2389 Rain on your Parade 二分图匹配--HK算法

    You’re giving a party in the garden of your villa by the sea. The party is a huge success, and everyone is here. It’s a warm, sunny evening, and a soothing wind sends fresh, salty air from the sea. The evening is progressing just as you had imagined. It could be the perfect end of a beautiful day.

    But nothing ever is perfect. One of your guests works in weather forecasting. He suddenly yells, “I know that breeze! It means its going to rain heavily in just a few minutes!” Your guests all wear their best dresses and really would not like to get wet, hence they stand terrified when hearing the bad news.
    You have prepared a few umbrellas which can protect a few of your guests. The umbrellas are small, and since your guests are all slightly snobbish, no guest will share an umbrella with other guests. The umbrellas are spread across your (gigantic) garden, just like your guests. To complicate matters even more, some of your guests can’t run as fast as the others.
    Can you help your guests so that as many as possible find an umbrella before it starts to pour? 

    Given the positions and speeds of all your guests, the positions of the umbrellas, and the time until it starts to rain, find out how many of your guests can at most reach an umbrella. Two guests do not want to share an umbrella, however. 

    虽然也是二分图匹配,但是需要用HK算法,匈牙利算法会超时

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<queue>
      4 using namespace std;
      5 typedef long long ll;
      6 const int MAXN=3005;//最大点数
      7 const int INF=0x3f3f3f3f;//距离初始值
      8 int Map[MAXN][MAXN];//二分图
      9 int cx[MAXN];//cx[i]表示左集合i顶点所匹配的右集合的顶点序号
     10 int cy[MAXN];//cy[i]表示右集合i顶点所匹配的左集合的顶点序号
     11 int n,m,dis;
     12 int dx[MAXN],dy[MAXN];
     13 bool vis[MAXN];
     14 int xp[3005],yp[3005],s[3005];
     15 int xu[3005],yu[3005];
     16 
     17 bool searchpath(){
     18     queue<int>Q;
     19     dis=INF;
     20     memset(dx,-1,sizeof(dx));
     21     memset(dy,-1,sizeof(dy));
     22     for(int i=1;i<=n;++i){
     23         //cx[i]表示左集合i顶点所匹配的右集合的顶点序号
     24         if(cx[i]==-1){
     25             //将未遍历的节点入队并初始化次节点距离为0
     26             Q.push(i);
     27             dx[i]=0;
     28         }
     29     }
     30     //广度搜索增广路径
     31     while(!Q.empty()){
     32         int u=Q.front();
     33         Q.pop();
     34         if(dx[u]>dis)break;
     35         //取右侧节点
     36         for(int i=1;i<=m;++i){
     37             //右侧节点的增广路径的距离
     38             if(Map[u][i]&&dy[i]==-1){
     39                 dy[i]=dx[u]+1;//v对应的距离为u对应距离加1
     40                 if(cy[i]==-1)dis=dy[i];
     41                 else{
     42                     dx[cy[i]]=dy[i]+1;
     43                     Q.push(cy[i]);
     44                 }
     45             }
     46         }
     47     }
     48     return dis!=INF;
     49 }
     50 
     51 //寻找路径深度搜索
     52 int findpath(int s){
     53     for(int i=1;i<=m;++i){
     54         //如果该点没有被遍历过并且距离为上一节点+1
     55         if(!vis[i]&&Map[s][i]&&dy[i]==dx[s]+1){
     56             //对该点染色
     57             vis[i]=1;
     58             if(cy[i]!=-1&&dy[i]==dis)continue;
     59             if(cy[i]==-1||findpath(cy[i])){
     60                 cy[i]=s;cx[s]=i;
     61                 return 1;
     62             }
     63         }
     64     }
     65     return 0;
     66 }
     67 
     68 //得到最大匹配的数目
     69 int MaxMatch(){
     70     int res=0;
     71     memset(cx,-1,sizeof(cx));
     72     memset(cy,-1,sizeof(cy));
     73     while(searchpath()){
     74         memset(vis,0,sizeof(vis));
     75         for(int i=1;i<=n;++i){
     76             if(cx[i]==-1)res+=findpath(i);
     77         }
     78     }
     79     return res;
     80 }
     81 
     82 int main(){
     83     int T;
     84     scanf("%d",&T);
     85     for(int q=1;q<=T;++q){
     86         memset(Map,0,sizeof(Map));
     87         int t;
     88         scanf("%d",&t);
     89         scanf("%d",&n);
     90         for(int i=1;i<=n;++i){
     91             scanf("%d%d%d",&xp[i],&yp[i],&s[i]);
     92         }
     93         scanf("%d",&m);
     94         for(int i=1;i<=m;++i){
     95             scanf("%d%d",&xu[i],&yu[i]);
     96         }
     97         for(int i=1;i<=n;++i){
     98             for(int j=1;j<=m;++j){
     99                 if((xp[i]-xu[j])*(ll)(xp[i]-xu[j])+(yp[i]-yu[j])*(ll)(yp[i]-yu[j])<=t*(ll)t*s[i]*s[i]){
    100                     Map[i][j]=1;
    101                 }
    102             }
    103         }
    104         printf("Scenario #%d:
    %d
    
    ",q,MaxMatch());
    105     }
    106     return 0;
    107 }
    View Code
  • 相关阅读:
    公众号开发笔记一
    公众号开发笔记一
    ArrayList,LinkedList和String
    ArrayList,LinkedList和String
    第56节:ArrayList,LinkedList和String
    第55节:Java当中的IO流-时间api(下)-上
    Java当中的IO流-时间api(下)-上
    当用python读取几十万行文本时,会出现什么状况?
    Python 如何定义只读属性?【新手必学】
    Python之数据分析工具包介绍以及安装【入门必学】
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/6592399.html
Copyright © 2011-2022 走看看