hdu3585(最大团)

链接;点击打开链接

题意:给出n个点找出k个点两两相连并使得最短边最长

代码:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int V,K,bestn;
double len[105*105],x[105],y[105],tmp[105][105];
int dp[105],sum[105][105],G[105][105];
void dfs(int ns,int dep){
    int i,j,u,v,cnt;
    if(ns==0){
    bestn=max(dep,bestn);
    return;
    }
    for(i=0;i<ns;i++){
        u=sum[dep][i];
        if(dep+V-u+1<=bestn||dep+dp[u]<=bestn)
        return;
        cnt=0;
        for(j=i+1;j<ns;j++){
            v=sum[dep][j];
            if(G[u][v])
            sum[dep+1][cnt++]=v;
        }
        dfs(cnt,dep+1);
    }
}
int judge(double mid){
    int i,j,ns;
    memset(G,0,sizeof(G));
    for(i=1;i<=V;i++)
    for(j=i+1;j<=V;j++)
    if(tmp[i][j]>=mid)
    G[i][j]=G[j][i]=1;
    bestn=0;
    for(i=V;i>=1;i--){
        ns=0;
        for(j=i+1;j<=V;j++){
            if(G[i][j])
            sum[1][ns++]=j;
        }
        dfs(ns,1);
        dp[i]=bestn;
        if(bestn>=K)
        return 1;
    }
    return 0;
}                                               //最大团模板
int main(){                                     //就是转换成二分最短边,将比最短边大
    int i,j,k,l,r,id,ans,mid;                   //的值全部连起来,用最大团判断是否点的
    while(scanf("%d%d",&V,&K)!=EOF){            //个数大于k
        id=1;
        for(i=1;i<=V;i++)
        scanf("%lf%lf",&x[i],&y[i]);
        for(i=1;i<=V;i++){
        tmp[i][i]=0;
        for(j=i+1;j<=V;j++){
        tmp[i][j]=tmp[j][i]=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
        len[id++]=tmp[i][j];
        }
        }                                       //用所有长度排序后二分下标,而不是直接
        sort(len+1,len+id);                     //二分长度
        l=1,r=id-1;
        while(l<=r){
            mid=(l+r)/2;
            if(judge(len[mid])){
            l=mid+1;
            ans=mid;
            }
            else
            r=mid-1;
        }
        printf("%.2lf\n",sqrt(len[ans]));
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值