转化为一个有向图,判断有向图是否有闭合环。如果有,则可以无限重复。如果没有,则不行。
转化的具体方式为,遍历输入条件的每一个边,然后把这个边的对应节点(比如A+对应A-)与这个条件的其他边相连(模拟现实情况中的两个正方形相连)。
网上代码的输入非常漂亮,用了两个函数,一个ID函数,将52个条件对应为了52个数字。异或可以用来转换相邻的偶数和奇数。
一道普通的DFS题
!vis[i]为剪枝,意思是只有i没有被遍历过才有继续dfs的必要。如果i被遍历过,那么这个节点一定不在环里面。
代码
#include<cstdio>
#include<cstring>
using namespace std;
int edge[52][52];
int vis[52];
int ID(char a,char b){
return (a-'A')*2+(b=='+'?0:1);
}
void ct(char a1,char a2,char b1,char b2){//对每个边都与其他非自身的边连接,即一个正方形内的点不能连接,这样会导致永远循环!!!!!!!!
if(a1=='0'||b1=='0')
return;
else{
int u=ID(a1,a2)^1;
int v=ID(b1,b2);
edge[u][v]++;
}
}
int dfs(int u){//返回是否有环,如果edge有环,那么实际上就是无限多个。如果edge无环,那么就是有限多个
vis[u]=-1;
for(int i=0;i<52;i++){
if(edge[u][i]){
if(vis[i]==-1) return 1;
else if(!vis[i]&&dfs(i)) return 1;
}
}
vis[u]==1;
return 0;
}
int cyc(){
for(int i=0;i<52;i++){
if(!vis[i]&&dfs(i))
return 1;
}
return 0;
}
int main(void){
int n;
// printf("%d",ID('A','+')^1);
while(scanf("%d",&n)!=EOF){
memset(edge,0,sizeof(edge));
memset(vis,0,sizeof(vis));
while(n--){
char s[10];
scanf("%s",s);
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++){
if(i!=j)
ct(s[j*2],s[j*2+1],s[i*2],s[i*2+1]);
}
}
}
printf("%s",(cyc()?"unbounded\n":"bounded\n"));
// for (int i=0;i<52;i++){
// for(int j=0;j<52;j++){
// if(edge[i][j])
// printf("%d to %d\n",i,j);
// }
// }
}
return 0;
}