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\n",r);

    }

    return 0;

}

 

你可能感兴趣的:(HDU)