题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1519
题目大意:求单回路数,参考了陈丹琦的论文和别人的代码,我用了最小表示法和括号表示法两种方法,据说最小表示法适用性更好,因为如果用广义括号表示法的话情况会很多,而最小表示法的情况讨论要简单一些,但是对于一些插头种类较少的题,比如说简单回路和简单路径,用括号表示法有相当大的优势,因为大多数情况下用位运算就可以了,效率很高。我的最小表示法跑了300多ms,而括号表示法只跑了70多ms。
最小表示法:
#include<stdio.h> #include<string.h> #define Max 1001000 #define Hash 30007 int code[15],ch[15],mp[15][15],ex,ey,n,m,cur; char str[15]; struct node { int size,next[Max],p[Hash]; __int64 state[Max],f[Max]; void init() { memset(p,-1,sizeof(p)); size=0; } void push(__int64 st,__int64 val) { int i,u=st%Hash; for(i=p[u];i!=-1;i=next[i]) { if(state[i]==st) { f[i]+=val; return; } } state[size]=st;f[size]=val; next[size]=p[u]; p[u]=size++; } }dp[2]; void decode(__int64 st) { for(int i=m;i>=0;i--) { code[i]=st&7; st>>=3; } } __int64 encode() { __int64 st=0; int cnt=1; memset(ch,-1,sizeof(ch)); ch[0]=0; for(int i=0;i<=m;i++) { if(ch[code[i]]==-1) ch[code[i]]=cnt++; st<<=3; st|=ch[code[i]]; } return st; } void shift() { for(int k=0;k<dp[cur].size;k++) { dp[cur^1].push(dp[cur].state[k]>>3,dp[cur].f[k]); } } void dpblank(int i,int j) { int k,l,left,up; for(k=0;k<dp[cur].size;k++) { decode(dp[cur].state[k]); left=code[j-1],up=code[j]; if(left&&up) { if(left==up) { if(i==ex&&j==ey) { code[j-1]=code[j]=0; dp[cur^1].push(encode(),dp[cur].f[k]); } } else { code[j-1]=code[j]=0; for(l=0;l<=m;l++) if(code[l]==up) code[l]=left; dp[cur^1].push(encode(),dp[cur].f[k]); } } else if(left) { if(mp[i][j+1]) { code[j-1]=0;code[j]=left; dp[cur^1].push(encode(),dp[cur].f[k]); } if(mp[i+1][j]) { code[j-1]=left,code[j]=0; dp[cur^1].push(encode(),dp[cur].f[k]); } } else if(up) { if(mp[i][j+1]) { code[j-1]=0;code[j]=up; dp[cur^1].push(encode(),dp[cur].f[k]); } if(mp[i+1][j]) { code[j-1]=up;code[j]=0; dp[cur^1].push(encode(),dp[cur].f[k]); } } else if(mp[i][j+1]&&mp[i+1][j]) { code[j-1]=code[j]=7; dp[cur^1].push(encode(),dp[cur].f[k]); } } } void dpblock(int i,int j) { for(int k=0;k<dp[cur].size;k++) dp[cur^1].push(dp[cur].state[k],dp[cur].f[k]); } void solve() { int i,j,k; __int64 ans=0; cur=0; dp[0].init(); dp[0].push(0,1); for(i=1;i<=n;i++) { dp[cur^1].init(); shift(); cur^=1; for(j=1;j<=m;j++) { dp[cur^1].init(); if(mp[i][j]) dpblank(i,j); else dpblock(i,j); cur^=1; } } for(k=0;k<dp[cur].size;k++) { ans+=dp[cur].f[k]; } printf("%I64d\n",ans); } int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF) { ex=0; memset(mp,0,sizeof(mp)); for(i=1;i<=n;i++) { scanf("%s",str+1); for(j=1;j<=m;j++) { if(str[j]=='.') mp[ex=i][ey=j]=1; } } if(ex==0) { printf("0\n");continue; } solve(); } return 0; }
括号表示法:
#include<stdio.h> #include<string.h> #define Max 1001000 #define Hash 30007 int n,m,ex,ey,cur,mp[15][15],a1,a2,a3,b1,b2,b3; int stack[15],f[15]; char str[15]; struct node { int size,next[Max],p[Hash],state[Max]; __int64 f[Max]; inline void init() { memset(p,-1,sizeof(p)); size=0; } inline void push(int st,__int64 val) { int i,u=st%Hash; for(i=p[u];i!=-1;i=next[i]) { if(state[i]==st) { f[i]+=val; return; } } state[size]=st;f[size]=val; next[size]=p[u]; p[u]=size++; } }dp[2]; inline void decode(int st) { int top=0; for(int i=0;i<=m;i++) { if((st&3)==1) stack[top++]=i; else if((st&3)==2) { f[stack[top-1]]=i; f[i]=stack[top-1]; top--; } st>>=2; } } inline void shift() { for(int k=0;k<dp[cur].size;k++) dp[cur^1].push(dp[cur].state[k]<<2,dp[cur].f[k]); } inline void dpblank(int i,int j) { int k,left,up; for(k=0;k<dp[cur].size;k++) { int st=dp[cur].state[k]; left=st&a3; up=st&b3; if(left&&up) { if(left==a1&&up==b2) { if(i==ex&&j==ey) dp[cur^1].push(st^left^up,dp[cur].f[k]); } else { if(left==a2&&up==b1) dp[cur^1].push(st^left^up,dp[cur].f[k]); if(left==a1&&up==b1) { decode(st); dp[cur^1].push(st^left^up^(3<<(2*f[j])),dp[cur].f[k]); } if(left==a2&&up==b2) { decode(st); dp[cur^1].push(st^left^up^(3<<(2*f[j-1])),dp[cur].f[k]); } } } else if(left) { if(mp[i][j+1]) dp[cur^1].push((st^left)|(left<<2),dp[cur].f[k]); if(mp[i+1][j]) dp[cur^1].push(st,dp[cur].f[k]); } else if(up) { if(mp[i][j+1]) dp[cur^1].push(st,dp[cur].f[k]); if(mp[i+1][j]) dp[cur^1].push((st^up)|(up>>2),dp[cur].f[k]); } else if(mp[i][j+1]&&mp[i+1][j]) dp[cur^1].push(st|a1|b2,dp[cur].f[k]); } } inline void solve() { int i,j,k; __int64 ans=0; cur=0; dp[0].init(); dp[0].push(0,1); for(i=1;i<=n;i++) { dp[cur^1].init(); shift(); cur^=1; b1=1;b2=2; for(j=1;j<=m;j++) { a1=b1;a2=b2;a3=a1|a2; b1<<=2;b2<<=2;b3=b1|b2; if(mp[i][j]) { dp[cur^1].init(); dpblank(i,j); cur^=1; } } } for(k=0;k<dp[cur].size;k++) ans+=dp[cur].f[k]; printf("%I64d\n",ans); } int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF) { ex=0; memset(mp,0,sizeof(mp)); for(i=1;i<=n;i++) { scanf("%s",str+1); for(j=1;j<=m;j++) { if(str[j]=='.') mp[ex=i][ey=j]=1; } } if(ex==0) { printf("0\n");continue; } solve(); } return 0; }