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;
}

 

posted @ 2013-09-09 21:02  fangguo  阅读(211)  评论(0编辑  收藏  举报