hdu 3656 DLX

思路:二分枚举建边,用DLX判断是否满足。

#include<set>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define clr(x,y) memset(x,y,sizeof(x))
#define pb push_back
#define mp make_pair
#define Maxn 20010
#define LL __int64
#define Abs(x) ((x)>0?(x):(-x))
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
#define inf 100000000
#define lowbit(x) (x&(-x))
#define Mod 1000000007
using namespace std;
int L[Maxn], R[Maxn], U[Maxn], D[Maxn];
int id, ans, S[Maxn], H[Maxn], C[Maxn];
int cnt,n,m;
double dis[110][110],edge[200000];
struct Point{
    double x,y;
}p[Maxn];
double Dis(Point a,Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool vis[130];
void Link(int r, int c)
{
    U[id] = c;
    D[id] = D[c];
    U[D[c]] = id;
    D[c] = id;
    if (H[r] < 0)
        H[r] = L[id] = R[id] = id;
    else
    {
        L[id] = H[r];
        R[id] = R[H[r]];
        L[R[H[r]]] = id;
        R[H[r]] = id;
    }
    S[c]++;
    C[id++] = c;
}
void Remove(int c)
{
    int i;
    for (i = D[c]; i != c; i = D[i])
    {
        L[R[i]] = L[i];
        R[L[i]] = R[i];
    }
}
void Resume(int c)
{
    int i;
    for (i = D[c]; i != c; i = D[i])
        L[R[i]] = R[L[i]] = i;
}
int A()
{
    int i, j, k, res;
    memset(vis, false,sizeof(vis));
    for (res = 0, i = R[0]; i; i = R[i])
    {
        if (!vis[i])
        {
            res++;
            for (j = D[i]; j != i; j = D[j])
            {
                for (k = R[j]; k != j; k = R[k]){
                    vis[C[k]] = true;
                  //  cout<<i<<" "<<j<<" "<<k<<" "<<C[k]<<endl;
                }
            }
        }
    }
    return res;
}
bool dfs (int step) {
    if (step + A() > m) return false;
    if (R[0] == 0) return true;
    int temp = inf, id;
    for (int i = R[0]; i ; i = R[i]) {
        if (S[i] < temp) {
            temp = S[i];
            id = i;
        }
    }
    for (int i = D[id]; i != id; i = D[i]) {
        Remove(i);
        for (int j = R[i]; j != i; j = R[j]) {
            Remove(j);
        }
        if (dfs(step + 1)) {
            return true;
        }
        for (int j = L[i]; j != i; j = L[j]) {
            Resume(j);
        }
        Resume(i);
    }
    return false;
}
void Init(int m)
{
    int i;
    for (i = 0; i <= m; i++)
    {
        R[i] = i + 1;
        L[i + 1] = i;
        U[i] = D[i] = i;
        S[i] = 0;
    }
    R[m] = 0;
    id = m + 1;
}
void build(int pos)
{
    int i,j;
    Init(n);
    for(i=1;i<=n;i++){
        H[i]=-1;
        for(j=1;j<=n;j++){
            if(dis[i][j]<=edge[pos])
                Link(i,j);
        }
    }
}
void solve()
{
    int i,j;
    int l,r,mid;
    l=1,r=cnt;
    while(l<r){
        mid=(l+r)>>1;
        build(mid);
        if(dfs(0))
            r=mid;
        else
            l=mid+1;
    }
    printf("%.6lf\n",edge[l]);
}
int main()
{
    int i,j,t;
    //freopen("ttt.txt","r",stdin);
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++){
            scanf("%lf%lf",&p[i].x,&p[i].y);
        }
        cnt=0;
        for(i=1;i<=n;i++){
            for(j=i+1;j<=n;j++){
                dis[i][j]=dis[j][i]=Dis(p[i],p[j]);
                edge[++cnt]=dis[i][j];
            }
            dis[i][i]=0;
        }
        edge[++cnt]=0;
        sort(edge+1,edge+1+cnt);
        int num=1;
        for(i=1;i<=cnt;i++){
            if(edge[i]!=edge[num]){
                edge[++num]=edge[i];
            }
        }
        cnt=num;
        solve();
    }
    return 0;
}

 

posted @ 2013-09-07 00:39  fangguo  阅读(188)  评论(0编辑  收藏  举报