//http://sqybi.com/works/dlxcn/ /* 同时有部分覆盖与完全覆盖时,尝试取某一行时,一定要先去掉部分覆盖的列,再去完全覆盖的列。 因为去完全覆盖的列时,会把部分覆盖的列的关系打乱,使后面再去部分覆盖时找不到了,无法结束。 hdu3957每个角色最多有两个身份,给出每个角色的身份的胜败关系,选出最少的角色的某个身份, 使得无论其它角色选择什么身份,至少有一个你选的角色打败它。 */ #include<stdio.h> #include<string.h> #include<iostream> using namespace std; const int maxr=55; const int maxc=110; const int maxn=11000; int L[maxn],R[maxn],U[maxn],D[maxn],RH[maxn],CH[maxn],ynum[maxc]; int sum,r,c,size,head; bool mat[maxr][maxc],vis[maxc]; int AddNode(int l,int r,int u,int d) { L[size]=l,R[size]=r,U[size]=u,D[size]=d; L[r]=R[l]=U[d]=D[u]=size; return size++; } void Make() { int i,j,k; memset(ynum,0,sizeof(ynum)); size=0; head=AddNode(size,size,size,size); for(i=0;i<c;i++) { CH[i+1]=i; AddNode(L[head],head,size,size); } for(i=0;i<r;i++) for(k=-1,j=0;j<c;j++) { if(!mat[i][j]) continue; RH[size]=i,CH[size]=j,ynum[j]++; if(k==-1) k=AddNode(size,size,U[j+1],j+1); else k=AddNode(k,R[k],U[j+1],j+1); } for(i=0;i<c;i++) if(!ynum[i]) L[R[i+1]]=L[i+1],R[L[i+1]]=R[i+1]; } void Remove(int c)//完全覆盖的去除c列元素的行 { L[R[c]]=L[c],R[L[c]]=R[c]; int i,j,k; for(i=U[c];i!=c;i=U[i]) for(j=R[i];j!=i;j=R[j]) ynum[CH[j]]--,U[D[j]]=U[j],D[U[j]]=D[j]; } void Resume(int c) { int i,j,k; for(i=D[c];i!=c;i=D[i]) for(j=L[i];j!=i;j=L[j]) ynum[CH[j]]++,U[D[j]]=D[U[j]]=j; L[R[c]]=R[L[c]]=c; } void Remove1(int c)//部分覆盖去除c列 { int i; for(i=U[c];i!=c;i=U[i]) L[R[i]]=L[i],R[L[i]]=R[i]; } void Resume1(int c) { int i; for(i=D[c];i!=c;i=D[i]) L[R[i]]=R[L[i]]=i; } int h() { int i,j,k,num=0; memset(vis,false,sizeof(vis)); for(i=R[head];i!=head&&i<=r;i=R[i]) if(!vis[CH[i]]) { num++; vis[CH[i]]=true; for(j=U[i];j!=i;j=U[j]) for(k=R[j];k!=j;k=R[k]) vis[CH[k]]=true; } return num; } void DFS(int t) { if(t+h()>=sum) return;//部分覆盖的IDA* if(R[head]==head||R[head]>r) { if(sum>t) sum=t; return; } int i,j,k; for(k=-1,i=R[head];i!=head&&i<=r;i=R[i]) if(k==-1||ynum[CH[i]]<ynum[CH[k]]) k=i; //printf("%d %d\n",t,k); for(i=U[k];i!=k;i=U[i]) { Remove1(i);//先去掉部分覆盖的 for(j=R[i];j!=i;j=R[j]) if(CH[j]<r) Remove1(j); for(j=R[i];j!=i;j=R[j])//再去完全覆盖 { if(CH[j]>=r) Remove(CH[j]+1); // else Remove1(j); //混着写是错的,无法正常结束 } DFS(t+1); for(j=L[i];j!=i;j=L[j]) { if(CH[j]>=r) Resume(CH[j]+1); // else Resume1(j); } for(j=L[i];j!=i;j=L[j]) if(CH[j]<r) Resume1(j); Resume1(i); } } int main() { int t,test=1,n,i,j,k,kk,u,v; scanf("%d",&t); while(t--) { scanf("%d",&n); memset(mat,false,sizeof(mat)); for(i=0;i<n;i++) { scanf("%d",&k); for(j=0;j<k;j++) { if(k==2) mat[i*2+j][i*2+(j^1)]=true; mat[i*2+j][i*2+j]=true; mat[i*2+j][n*2+i]=true; scanf("%d",&kk); while(kk--) { scanf("%d%d",&u,&v); mat[i*2+j][u*2+v]=true; } } } r=n*2,c=n*3; Make(); sum=r; DFS(0); printf("Case %d: %d\n",test++,sum); } return 0; }
//hdu3111求9*9的数独 #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; const int maxr=1100; const int maxc=410; const int maxn=maxr*maxc; int o[maxn],L[maxn],R[maxn],U[maxn],D[maxn],RH[maxn],CH[maxn],ynum[maxc]; int size,head,r,c,g[10][10]; bool mat[maxr][maxc]; int AddNode(int l,int r,int u,int d) { L[size]=l,R[size]=r,U[size]=u,D[size]=d; L[r]=R[l]=U[d]=D[u]=size; return size++; } void Remove(int c)//删除c列 { L[R[c]]=L[c],R[L[c]]=R[c]; int i,j; for(i=U[c];i!=c;i=U[i]) for(j=R[i];j!=i;j=R[j]) D[U[j]]=D[j],U[D[j]]=U[j]; } void Resume(int c)//恢复c列 { int i,j; for(i=D[c];i!=c;i=D[i]) for(j=L[i];j!=i;j=L[j]) D[U[j]]=U[D[j]]=j; L[R[c]]=R[L[c]]=c; } bool DFS(int kk) { if(R[head]==head) return true; int i,j,k; for(k=-1,i=R[head];i!=head;i=R[i])//找含最少元素的列 if(k==-1||ynum[CH[i]]<ynum[CH[k]]) k=i; Remove(k); for(i=U[k];i!=k;i=U[i])//枚举这列元素所在的行 { o[kk]=RH[i]; for(j=R[i];j!=i;j=R[j]) Remove(CH[j]+1); if(DFS(kk+1)) return true; for(j=L[i];j!=i;j=L[j]) Resume(CH[j]+1); } Resume(k); return false; } void Make() { int i,j,k; memset(mat,false,sizeof(mat)); for(i=0;i<9;i++) for(j=0;j<9;j++) for(k=1;k<=9;k++) if(!g[i][j]||g[i][j]==k) { mat[i*9*9+j*9+k-1][i*9+j]=true; mat[i*9*9+j*9+k-1][9*9+i*9+k-1]=true; mat[i*9*9+j*9+k-1][2*9*9+j*9+k-1]=true; mat[i*9*9+j*9+k-1][3*9*9+(i/3*3+j/3)*9+k-1]=true; } r=9*9*9; c=4*9*9; size=0,head=0; memset(ynum,0,sizeof(ynum)); AddNode(size,size,size,size); for(i=0;i<c;i++) { CH[size]=i; AddNode(L[head],head,size,size); } for(i=0;i<r;i++) for(k=-1,j=0;j<c;j++) { if(!mat[i][j]) continue; RH[size]=i,CH[size]=j,ynum[j]++; if(k==-1) k=AddNode(size,size,U[j+1],j+1); else k=AddNode(k,R[k],U[j+1],j+1); } } int main() { int t,i,j; char ch[110]; scanf("%d",&t); getchar(); while(t--) { for(i=0;i<9;i++) { gets(ch); for(j=0;j<9;j++) { if(ch[j]=='?') g[i][j]=0; else g[i][j]=ch[j]-'0'; } } Make(); if(!DFS(0)) printf("impossible\n"); else { sort(o,o+81); for(i=0;i<81;i++) { printf("%d",o[i]%9+1); if(i%9==8) printf("\n"); } } if(t) { printf("---\n"); gets(ch); } } return 0; }