这道题真的卡了我好久,一直想错方向了,想用并查集判断连通,像欧拉回路那样= =也想到了拓扑排序,但一直不知道怎么建边。收集了一下dalao们的想法,终于有思路了:比如一个正方形是A+A-B+B-;那么从A+开始,有三种方式A-B+B-;如果走到A-,那么下个出口一定是A+,此时就进入另一个正方形内部了,重复执行即可,所以只需要标记一下该点是否走过即可判环;
这里看喜好建图,邻接矩阵/表均可;
tips:如果是邻接表千万别开内存池,会RE
下面上代码:
#include<bits/stdc++.h>
using namespace std;
int b[52];//判断字符是否出现过
bool valid=false;
struct edge
{
int to;//代表对应边,比如这个点是A+,那么to就代表A-
edge *next;
};
struct Node
{
edge *first;
int flag=0;//1表示正在循环,-1表示循环结束
}nodes[52];//0-25依次对应A+------Z+;26-51依次对应A- -------Z-;
void addedge(char a,char b,int u)//建立邻接表;
{
int to;
if(b=='+')
to=a-'A'+26;
else
to=a-'A';
edge *e=new edge;
e->to=to;
e->next=nodes[u].first;
nodes[u].first=e;
}
int getu(char a,char b)
{
if(b=='+')
return a-'A';
else
return a-'A'+26;
}
void dfs(int u)
{
if(nodes[u].flag==1)
{
valid=true;
return;
}
if(nodes[u].flag==-1)
return;
nodes[u].flag=1;
edge *e=nodes[u].first;
while(e)
{
dfs(e->to);
e=e->next;
}
nodes[u].flag=-1;//标记为1的原因是如果该点已经递归执行了所有可行的方式但仍不成环
//则下一次从其他点递归可以略过该点,因为从该点走不可能存在环;
}
void init()
{
valid=false;
memset(nodes,0,sizeof(nodes));
memset(b,0,sizeof(b));
}
int main()
{
int n;
while(cin>>n)
{
init();
string str;
for(int i=0;i<n;i++)
{
cin>>str;
for(int j=0;j<str.size();j+=2)
{
if(str[j]!='0')
{
int u=getu(str[j],str[j+1]);
b[u]=1;
for(int m=0;m<str.size();m+=2)
{
if(m!=j&&str[m]!='0')
addedge(str[m],str[m+1],u);
}
}
}
}
for(int i=0;i<52;i++)
{
if(b[i])
{
dfs(i);
if(valid)
break;
}
}
if(valid)
cout<<"unbounded"<<endl;
else
cout<<"bounded"<<endl;
}
return 0;
}