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;

}

 

你可能感兴趣的:(HDU)