HDU 3585 maximum shortest distance 最大团+简单的二分思想

题意:给你n个点,然后你可以从里面找出k个点,然后使得k个点中的最短距离最大。


想法:直接二分枚举最大距离,然后把满足的边找出来,然后就看看这些点的最大独立点集,如果个数>=k,那么显然长度可能可以更长一些,所以继续枚举,如果<k,那么缩短长度以便于增加点边的个数,来得到更大的点集。这里的最大团用到了dp优化。


#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int nodes=55;
int n,k;
int x[nodes],y[nodes];
bool map[nodes][nodes];
int mx,dp[nodes],stk[nodes][nodes];
double dis[nodes][nodes],l[nodes*nodes];
double Dis(int a,int b,int c,int d)
{
    int x=a-c;
    int y=b-d;
    return sqrt(x*x*1.0+y*y*1.0);
}
int dfs(int ns,int dep)
{
    if(ns==0)
    {
        if(dep>mx) mx=dep;
        return 1;
    }
    for(int i=0;i<ns;i++)
    {
        int u=stk[dep][i];
        if(dep+n-u+1<=mx) return 0;
        if(dep+dp[u]<=mx) return 0;
        int cnt=0;
        for(int j=i+1;j<ns;j++)
        {
            int v=stk[dep][j];
            if(map[u][v])
            {
                stk[dep+1][cnt++]=v;
            }
        }
        dfs(cnt,dep+1);
    }
    return 0;
}
int cal(int mid)
{
    memset(map,false,sizeof(map));
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(dis[i][j]>=l[mid])
            {
                map[i][j]=map[j][i]=true;
            }
        }
    }
    mx=0;
    int ns;
    for(int i=n;i>=1;i--)
    {
        ns=0;
        for(int j=i+1;j<=n;j++)
        {
            if(map[i][j])
            {
                stk[1][ns++]=j;
            }
        }
        dfs(ns,1);
        dp[i]=mx;
        if(mx>=k) return 1;
    }
    return 0;
}
int main()
{
    while(~scanf("%d%d",&n,&k))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x[i],&y[i]);
        }
        int nn=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                dis[j][i]=dis[i][j]=Dis(x[i],y[i],x[j],y[j]);
                l[++nn]=dis[i][j];
            }
            dis[i][i]=0;
        }
        sort(l+1,l+nn+1);
        int lft=1,rht=nn,ans=1;
        while(lft<=rht)
        {
            int mid=(lft+rht)/2;
            if(cal(mid))
            {
                ans=mid;
                lft=mid+1;
            }
            else rht=mid-1;
        }
        printf("%.2lf\n",l[ans]);
    }
    return 0;
}



你可能感兴趣的:(HDU 3585 maximum shortest distance 最大团+简单的二分思想)