hdu 3663 DLX

思路:把每个点拆成(d+1)*n列,行数为可拆分区间数。对所有的有i号点拆分出来的行都要建一条该行到i列的边,那么就能确保有i号点拆出来的行只能选择一行。

#include<set>

#include<cmath>

#include<queue>

#include<cstdio>

#include<vector>

#include<string>

#include<cstdlib>

#include<cstring>

#include<iostream>

#include<algorithm>

#define pb push_back

#define mp make_pair

#define Maxn 1010

#define Maxm 80002

#define LL __int64

#define Abs(x) ((x)>0?(x):(-x))

#define lson(x) (x<<1)

#define rson(x) (x<<1|1)

#define inf 100000

#define lowbit(x) (x&(-x))

#define clr(x,y) memset(x,y,sizeof(x))

#define Mod 1000000007

using namespace std;

int U[Maxn*450],D[Maxn*450],L[Maxn*450],R[Maxn*450],S[Maxn*450],H[Maxn],C[Maxn*450],road[Maxn],id,d,n,m;

int g[70][70],row[Maxn*450];

int vi[Maxn];

struct interv{

    int s,e,i;

    int operator <(const interv &temp) const{

        if(s==temp.s)

            return e>temp.e;

        return s<temp.s;

    }

}p[Maxn],ans[Maxn];

void init(int n)

{

    int i;

    for(i=0;i<=n;i++){

        D[i]=U[i]=i;

        L[i+1]=i;

        R[i]=i+1;

        S[i]=0;

    }

    R[n]=0;

    id=n+1;

    memset(H,-1,sizeof(H));

}

void ins(int r,int c)

{

    int i,j;

    D[id]=D[c];

    U[id]=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]++;

    row[id]=r;

    C[id++]=c;

}

void Remove(int c)

{

    int i,j;

    L[R[c]]=L[c];

    R[L[c]]=R[c];

    for(i=D[c];i!=c;i=D[i]){

        for(j=R[i];j!=i;j=R[j]){

            D[U[j]]=D[j];

            U[D[j]]=U[j];

            S[C[j]]--;

        }

    }

}

void Resume(int c)

{

    int i,j;

    L[R[c]]=c;

    R[L[c]]=c;

    for(i=D[c];i!=c;i=D[i]){

        for(j=R[i];j!=i;j=R[j]){

            D[U[j]]=j;

            U[D[j]]=j;

            S[C[j]]++;

        }

    }

}

bool dfs(int step)

{

    int i,j,k,c,temp;

    if(R[0]==0){

        for(i=0;i<step;i++)

        vi[ans[road[i]].i]=road[i];

        for(i=1;i<=n;i++){

            if(!vi[i]) printf("0 0\n");

            else printf("%d %d\n",ans[vi[i]].s,ans[vi[i]].e);

        }

        return true;

    }

    temp=inf;

    for(i=R[0];i;i=R[i]) if(S[i]<temp){

        temp=S[i];

        c=i;

    }

    Remove(c);

    for(i=D[c];i!=c;i=D[i]){

        road[step]=row[i];

        for(j=R[i];j!=i;j=R[j]){

            Remove(C[j]);

        }

        if(dfs(step+1))

            return true;

        for(j=L[i];j!=i;j=L[j])

            Resume(C[j]);

    }

    Resume(c);

    return false;

}

void build()

{

    int i,j,sz,k,r;

    init(n*(d+1));

    int cnt=1;

    for(i=1;i<=n;i++){

        for(j=p[i].s;j<=p[i].e;j++){

            for(k=p[i].s;k<=j;k++){

                ins(cnt,i);

                ans[cnt].s=k,ans[cnt].e=j,ans[cnt].i=i;

                for(r=1;r<=n;r++){

                    if(!g[i][r]) continue;

                    for(int d=k;d<=j;d++){

                        ins(cnt,n+(d-1)*n+r);

                    }

                }

                cnt++;

            }

        }

        ins(cnt,i);

        ans[cnt].s=0,ans[cnt].e=0,ans[cnt].i=i;

        cnt++;

    }

}

int main()

{

    int i,j,u,v;

    while(scanf("%d%d%d",&n,&m,&d)!=EOF){

        memset(g,0,sizeof(g));

        for(i=1;i<=m;i++){

            scanf("%d%d",&u,&v);

            g[u][v]=g[v][u]=1;

        }

        for(i=1;i<=n;i++){

            g[i][i]=1;

            scanf("%d%d",&p[i].s,&p[i].e);

            p[i].i=i;

        }

        build();

        if(!dfs(0))

            printf("No solution\n");

        printf("\n");

    }

    return 0;

}

 

你可能感兴趣的:(HDU)