标签:
解析:裸的精确覆盖问题,不过要加优化,不过也是模板。
#include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; const int INF=1e9+7; const int ms=60; const int maxn=ms*ms; int N,M,ans; struct DLX { int n,id; int L[maxn],R[maxn],U[maxn],D[maxn]; int C[maxn],S[maxn],loc[maxn][2]; void init(int nn=0) //传列长 { n=nn; for(int i=0;i<=n;i++) U[i]=D[i]=i,L[i]=i-1,R[i]=i+1; L[0]=n; R[n]=0; id=n; memset(S,0,sizeof(S)); } void AddRow(int x,int col,int A[]) //传入参数是行标号,列长,列数组 { bool has=false; int first=id+1; for(int y=1;y<=col;y++) { if(A[y]==0) continue; has=true; ++id; L[id]=id-1; R[id]=id+1; D[id]=y; U[id]=U[y]; D[U[y]]=id; U[y]=id; loc[id][0]=x,loc[id][1]=y; C[id]=y; S[y]++; } if(!has) return; R[id]=first; L[first]=id; } void Remove(int Size) { for(int j=D[Size];j!=Size;j=D[j])//将左右两边连接 L[R[j]]=L[j],R[L[j]]=R[j]; } void Resume(int Size) { for(int j=U[Size];j!=Size;j=U[j])//恢复 L[R[j]]=R[L[j]]=j; } bool vis[ms];//标记行是否访问过 int h() //启发式函数 { int ret=0; int i,j,k; memset(vis,0,sizeof(vis)); for(i=R[0];i;i=R[i]) { if(vis[i]) continue; ret++; for(j=D[i];j!=i;j=D[j]) //所有关联的标记了 for(k=R[j];k!=j;k=R[k]) vis[C[k]]=1; } return ret; } void dfs(int step) { if(step+h()>=ans) return; if(R[0]==0){ ans=min(ans,step); return; } int Min=INF,c=-1; for(int i=R[0];i;i=R[i]) if(Min>S[i]){ Min=S[i]; c=i; } for(int i=D[c];i!=c;i=D[i]) { Remove(i); for(int j=R[i];j!=i;j=R[j]) Remove(j); dfs(step+1); for(int j=L[i];j!=i;j=L[j]) Resume(j); Resume(i); } return; } }dlx; int Mart[ms][ms]; int main() { while(scanf("%d%d",&N,&M)!=EOF) { dlx.init(N); ans=55; memset(Mart,0,sizeof(Mart)); for(int i=1;i<=N;i++) Mart[i][i]=1; while(M--) { int x,y; scanf("%d%d",&x,&y); Mart[x][y]=Mart[y][x]=1; } for(int i=1;i<=N;i++) dlx.AddRow(i,N,Mart[i]); dlx.dfs(0); printf("%d\n",ans); } return 0; }
代码
Hdu3498-whosyourdaddy(精确覆盖模板题)
标签:
原文地址:http://www.cnblogs.com/wust-ouyangli/p/5747090.html