zoukankan      html  css  js  c++  java
  • hdu 4606 Occupy Cities

    http://acm.hdu.edu.cn/showproblem.php?pid=4606

    两点之间如果有线段相隔的话,他们的最短路就需要经过线段的端点

    把所有线段的端点也加入点数组中,求任意两个点的距离(可达的话,没有其他线段阻挡)

    然后对所有的点进行floyd  可以求出任意两点的最短路

    然后二分所需容量 根据容量和要求的顺序进行建图,求最小覆盖路径(匈牙利算法)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<cmath>
    #include<set>
    #include<map>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<queue>
    #include<stdexcept>
    #include<bitset>
    #include<cassert>
    #include<deque>
    #include<numeric>
    
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned int uint;
    typedef pair<int,int> pp;
    const double eps=1e-9;
    const int INF=0x3f3f3f3f;
    const ll MOD=1000000007;
    const int N=510;
    double x[N],y[N];
    double dist[N][N];
    int schedule[N];
    bool visited[N];
    bool link[N][N];
    int f[N];
    int lr(double x1,double y1,double x2,double y2)
    {
        double tmp=x1*y2-x2*y1;
        if(abs(tmp)<eps)
        return 0;
        if(tmp>=eps)
        return 1;
        return -1;
    }
    bool dfs(int x,int n)
    {
        for(int i=x+1;i<=n;++i)
        if(link[x][i]&&!visited[i])
        {
            visited[i]=true;
            if(f[i]==-1||dfs(f[i],n))
            {
                f[i]=x;
                return true;
            }
        }
        return false;
    }
    int needSoldier(int n,double d)
    {
        memset(link,false,sizeof(link));
        for(int i=1;i<=n;++i)
        for(int j=i+1;j<=n;++j)
        if(d-dist[schedule[i]][schedule[j]]>=eps)
        link[i][j]=true;
        memset(f,-1,sizeof(f));
        int sum=0;
        for(int i=1;i<=n;++i)
        {
            memset(visited,false,sizeof(visited));
            if(dfs(i,n))
            ++sum;
        }
        return (n-sum);
    }
    double bar(int l,int r,int n,int ln)
    {
        for(int i=n+1;i<=ln;i=i+2)
        {
            double x1=x[r]-x[l];
            double y1=y[r]-y[l];
            double x2=x[i]-x[l];
            double y2=y[i]-y[l];
            int k1=lr(x1,y1,x2,y2);
            x2=x[i+1]-x[l];
            y2=y[i+1]-y[l];
            int k2=lr(x1,y1,x2,y2);
            if(k1==0||k2==0||k1==k2)
            continue;
            x1=x[i+1]-x[i];
            y1=y[i+1]-y[i];
            x2=x[l]-x[i];
            y2=y[l]-y[i];
            k1=lr(x1,y1,x2,y2);
            x2=x[r]-x[i];
            y2=y[r]-y[i];
            k2=lr(x1,y1,x2,y2);
            if(k1==0||k2==0||k1==k2)
            continue;
            return INF;
        }
        return sqrt((x[r]-x[l])*(x[r]-x[l])+(y[r]-y[l])*(y[r]-y[l]));
    }
    int main()
    {
        //freopen("data.in","r",stdin);
        //freopen("1007.in","r",stdin);
        //freopen("my.out","w",stdout);
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n,m,p;
            scanf("%d %d %d",&n,&m,&p);
            for(int i=1;i<=n;++i)
            scanf("%lf %lf",&x[i],&y[i]);
            int ln=n;
            while(m--)
            {
                ++ln;
                scanf("%lf %lf",&x[ln],&y[ln]);
                ++ln;
                scanf("%lf %lf",&x[ln],&y[ln]);
            }
            for(int i=1;i<=n;++i)
            scanf("%d",&schedule[i]);
            for(int i=1;i<=ln;++i)
            for(int j=i;j<=ln;++j)
            {
                if(i==j) dist[i][j]=0.0;
                else
                dist[i][j]=dist[j][i]=bar(i,j,n,ln);
            }
            for(int l=1;l<=ln;++l)
            for(int i=1;i<=ln;++i)
            for(int j=1;j<=ln;++j)
            if(dist[i][j]>dist[i][l]+dist[l][j])
            dist[i][j]=dist[i][l]+dist[l][j];
            /*
            for(int i=1;i<=n;++i)
            {
                for(int j=1;j<=n;++j)
                cout<<dist[i][j]<<" ";cout<<endl;
            }*/
            double l=0.0,r=1000000.0;
            double ep=1e-6;
            while(abs(r-l)>ep)
            {
                double mid=(l+r)/2;
                if(needSoldier(n,mid)<=p)
                r=mid;
                else
                l=mid;
            }
            printf("%.2lf
    ",r);
        }
        return 0;
    }
    
  • 相关阅读:
    并发编程(贰):线程池浅析
    并发编程(壹):创建线程的三种方式及其对比
    Spring Boot使用@Async实现异步调用:自定义线程池
    parallel stream-不能随便使用
    Java 8新特性(四):新的时间和日期API
    Java 8新特性(三):Optional类
    Java 8新特性(二):Stream API
    Java 8新特性(一):Lambda表达式
    ES日期存储
    String,StringBuffer,StringBuillder的底层结构
  • 原文地址:https://www.cnblogs.com/liulangye/p/3215289.html
Copyright © 2011-2022 走看看