hdu 3585 maximum shortest distance(二分+最大团)

二分距离,求最大团,看是否>=K

View Code
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
using namespace std;
const int N = 50+10;
int dis[N][N],dd[N*N];
int dp[N];
bool inset[N],g[N][N];
int n,best,ord[N],deg[N];
bool found;
inline void Memcpy(bool *d,bool *s)
{   
    for(int i=0;i<n;i++)   
        d[i]=s[ord[i]];
}
bool cmp(int a,int b)
{  
    return deg[a]<deg[b];
}
inline int find(int start,bool *s)
{   
    for(int i=start+1;i<n;i++)   
        if(s[i])  
            return i; 
    return -1;
}
void clique(bool *s,int start,int len)
{   
    int first=find(start,s),i;  
    if(first==-1) 
    {       
        if(len>best)   
        {    
            best=len;   
            found=true;  
        }    
        return ; 
    }   
    bool tmp[N];
    while(first!=-1) 
    {       
        if(len+n-start<=best || len+dp[first]<=best)  
            return ;      
        tmp[first]=false;   
        for(i=first+1;i<n;i++)    
            tmp[i]=s[i]&g[ord[first]][ord[i]];  
        clique(tmp,first,len+1);   
        if(found) return ;      
        first=find(first,s);  
    }
}
inline int get_clique(int dist)
{
    memset(g,false,sizeof(g));
    memset(deg,0,sizeof(deg));
    memset(dp,0,sizeof(dp));
    for(int i=0;i<n;i++)
    {
        ord[i]=i;
        g[i][i]=true;
        for(int j=i+1;j<n;j++)
        {
            if(dis[i][j]>=dist)
            {
                g[i][j]=g[j][i]=true;
                deg[i]++,deg[j]++;
            }
        }
    }
    sort(ord,ord+n,cmp);
    best=0;dp[n-1]=1;
    for(int i=n-2;i>=0;i--)
    {
        Memcpy(inset,g[ord[i]]);
        found=false;
        clique(inset,i,1);
        dp[i]=best;
    }
    return dp[0];
}
struct Point
{
    int x, y;
}p[N];
inline int get_dis(Point a,Point b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int main()
{
    int k;
    while(scanf("%d %d",&n,&k)==2)
    {
        for(int i=0;i<n;i++)
            scanf("%d %d",&p[i].x,&p[i].y);
        int t=0;
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                dis[i][j]=dis[j][i]=get_dis(p[i],p[j]);
                dd[t++]=dis[i][j];
            }
        }
        sort(dd,dd+t);
        int left=0,right=t-1,mid;
        while(left<=right)
        {
            mid=(left+right)>>1;
            if(get_clique(dd[mid])>=k)
                left=mid+1;
            else right=mid-1;
        }
        printf("%.2f\n",sqrt(double(dd[left-1])));
    }
    return 0;
}

 

posted @ 2012-04-13 09:24  枕边梦  阅读(438)  评论(0编辑  收藏  举报