紫书刷题记录 UVa1572 自组合

这道题真的卡了我好久,一直想错方向了,想用并查集判断连通,像欧拉回路那样= =也想到了拓扑排序,但一直不知道怎么建边。收集了一下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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值