hdu 3585(二分+最大团)
如果对团的知识不够了解的可以看看牛人的
http://www.cnblogs.com/pushing-my-way/archive/2012/08/08/2627993.html
题意:有n个点求最远距离的k个点的最短的那条边。
思路:我们可以求出任意两点的距离,然后二分距离,求K个点的最大团。
#include<iostream> #include<cmath> #include<algorithm> using namespace std; const int N=55; double map[N][N]; struct node { int x,y; }point[N]; int dp[N],stk[N][N]; int mx,n,K; double pp[N*N]; double dist(int x1,int y1,int x2,int y2) { return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)*1.0); } int dfs(int ns,int dep,int dis) { if(0==ns) { if(dep>mx) { mx=dep; } return 1; } int i,j,k,p,cnt; for(i=0;i<ns;i++) { k=stk[dep][i];cnt=0; if(dep+n-k<=mx)return 0; if(dep+dp[k]<=mx)return 0; for(j=i+1;j<ns;j++) { p=stk[dep][j]; if(map[k][p]>=dis) { stk[dep+1][cnt++]=p; } } dfs(cnt,dep+1,dis); } return 0; } int clique(double dis) { int i,j,ns; for(mx=0,i=n-1;i>=0;i--) { for(ns=0,j=i+1;j<n;j++) if(map[i][j]>=dis)stk[1][ns++]=j; dfs(ns,1,dis); dp[i]=mx; } return mx; } int main() { int i,j; while(scanf("%d%d",&n,&K)!=EOF) { int a=0; for(i=0;i<n;i++) { scanf("%d%d",&point[i].x,&point[i].y); map[i][i]=0; for(j=0;j<i;j++) { map[i][j]=map[j][i]=dist(point[i].x,point[i].y,point[j].x,point[j].y); pp[a++]=map[i][j]; } } sort(pp,pp+a); int left=0; int right=a; double mi; while (right>left) { int mid=(right+left)>>1; int t=clique(pp[mid]); if(t==K) { mi=pp[mid]; left++;//找到了符合条件的,但是要求是最大的,所以还要继续造符合要求的 } else if(t>K) left=mid; else right=mid; } printf("%.2lf\n",mi); } return 0; }