Chieh's Blog

Because Of Coding

ZOJ Problem Set - 3156 Taxi

Chieh posted @ 2015年7月21日 15:19 in ZOJ , 289 阅读

飞机票:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3127

题意:给你n个人n<=100,m辆车,n<=m<=100,然后给你n+m个坐标代表人和车的位置,最后再给你个速度v,求出最少的时间,使得每个人都有一辆车。(其中每个人都是同步进行的)

分析:这种题的话,就是相当于把n个人匹配到m辆车的n辆中,可以用二分图匹配算法,匈牙利的话是O(VE)那怎么求这个最少时间呢,其实可以二分求,然后每次二分的时间t,我们可以用O(nm)的时间,求的用t的时间,n个人可以和m辆车的哪几辆匹配,然后建图,跑一边匈牙利,如果可以最大匹配的话,那么这个时间是ok的,那么我们把上限变为t-0.001,因为要保留两位小数,反之把下限变为t+0.001,继续二分,最后输出答案即可。复杂的为logT*(n*m+VE),还是ok的,因为n和m比较小,最后啪啪啪就可以AC了

/*
Author:Chieh
Because Of Coding
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#define LL long long
#define INF 1e9
#define EPS 1e-9
using namespace std;
const int maxn=123;
struct he
{
    double x,y;
} Sky[2][maxn];
int n,m;
double ai[maxn][maxn];
double l,r;
double calT(int i,int j,double v)
{
    double dis=sqrt((Sky[0][i].x-Sky[1][j].x)*(Sky[0][i].x-Sky[1][j].x)+(Sky[0][i].y-Sky[1][j].y)*(Sky[0][i].y-Sky[1][j].y));
    return dis/v;
}
void init()
{
    for(int i=1; i<=n; i++)scanf("%lf%lf",&Sky[0][i].x,&Sky[0][i].y);
    for(int i=1; i<=m; i++)scanf("%lf%lf",&Sky[1][i].x,&Sky[1][i].y);
    double v;
    scanf("%lf",&v);
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            ai[i][j]=calT(i,j,v);
        }
    }
    r=2000000.0/v;

}
bool bi[maxn][maxn];
int Link[maxn];
bool vis[maxn];
bool DFS(int now)
{
    for(int i=1; i<=m; i++)
    {
        if(bi[now][i]&&!vis[i])
        {
            vis[i]=1;
            if(Link[i]==0||DFS(Link[i]))
            {
                Link[i]=now;
                return true;
            }
        }
    }
    return false;
}
void play()
{
    double MIN=r;
    l=0;
    while(l<=r)
    {
        double mid=(l+r)/2;
        memset(bi,0,sizeof(bi));
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                if(ai[i][j]<=mid)bi[i][j]=1;
            }
        }
        memset(Link,0,sizeof(Link));
        bool flag=1;
        for(int i=1; i<=n; i++)
        {
            memset(vis,0,sizeof(vis));
            if(DFS(i))continue;
            flag=0;
            break;
        }
        if(flag)
        {
            MIN=min(MIN,mid);
            r=mid-0.001;
        }
        else
        {
            l=mid+0.001;
        }

    }
    printf("%.2f\n",MIN);

}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        play();
    }
    //  cout << "Hello world!" << endl;
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter