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;
}
原文地址:https://www.cnblogs.com/liulangye/p/3215289.html