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
  • 相关阅读:
    【WCF学习随笔三】初见WCF。
    【WCF学习随笔二】第一个WebService应用。
    【WCF学习随笔一】序言。
    .NET Framework 4.5.1 开源了是广大程序员的巨大财富。
    数据逆向传递 unwind segue
    segue生命周期
    FusionChart学习笔记(部分)
    图解MonoForAndroid开发环境搭建
    jdbc_odbc SQLserver 驱动安装及测试
    关键词:CodeSmith工具、Money类型、__UNKNOWN__
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/6592399.html
Copyright © 2011-2022 走看看