uva 1572 self-assembly ——yhx
1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 using namespace std; 5 int map[60][60],cnt[60]; 6 queue<int> q; 7 char s[10]; 8 int main() 9 { 10 int i,j,k,m,n,p,t,x,y,z,w,temp[5]; 11 while (~scanf("%d",&n)) 12 { 13 memset(map,0,sizeof(map)); 14 memset(cnt,0,sizeof(cnt)); 15 while (!q.empty()) q.pop(); 16 for (i=1;i<=n;i++) 17 { 18 scanf("%s",s); 19 t=0; 20 for (j=0;j<=6;j+=2) 21 if (s[j]!='0') 22 { 23 if (s[j+1]=='+') 24 temp[++t]=(s[j]-'A')*2; 25 else 26 temp[++t]=(s[j]-'A')*2+1; 27 } 28 for (j=1;j<=t;j++) 29 for (k=j+1;k<=t;k++) 30 map[temp[j]^1][temp[k]]=map[temp[k]^1][temp[j]]=1; 31 } 32 for (i=0;i<=51;i++) 33 for (j=0;j<=51;j++) 34 if (map[i][j]) cnt[j]++; 35 t=0; 36 for (i=0;i<=51;i++) 37 if (!cnt[i]) 38 { 39 t++; 40 q.push(i); 41 } 42 while (!q.empty()) 43 { 44 x=q.front(); 45 q.pop(); 46 for (i=0;i<=51;i++) 47 if (map[x][i]) 48 { 49 cnt[i]--; 50 if (!cnt[i]) 51 { 52 q.push(i); 53 t++; 54 } 55 } 56 } 57 if (t<52) printf("unbounded\n"); 58 else printf("bounded\n"); 59 } 60 }
算法实现其实很简单,关键需要想明白。
只要边上的标号重复,那就一定可以通过不断的翻转无限延伸。
于是我们可以把每种标号看成一个点,每个正方形看成若干条边(比如,正方形上有两条边标号分别是A+,B-,那就分别连A-→B-,B+→A+,表示如果目前有一条边缘是A-,那么就可以有一个边缘是B-。
如果图中存在环,那么就说明标号会重复了,也就是会无限延伸。
拓扑排序或DFS均可。
小技巧:A+记为0,A-记为1,B+记为2,B-记为3,以此类推。每次求相反符号的标号只需^1。