poj1094

题意:给出一些字母之间的大小关系,问是否能确定这些字母唯一的顺序。

输出的要求是当可以确定大小关系时则从小到大输出这些字母,

如果有环则输出有环,不能确定关系则输出无法确定。


思路:每进来一条边则对这些边进行一次拓扑排序,如果得到的序列包括所有的字母,则输出。

之后没有被标记过的点进行一次DFS,发现有环则输出有环。

当所有边都检查完还没有找到一个包括所有字母的序列也没发现环则输出无法确定顺序。

(程序的运行时间是964ms几乎压线过的,感觉拓扑那里没什么优化的余地,

但是DFS那里或许直接检查拓扑结束后有没有剩余的点算法上也行的通)

别忘了!!!!!(昨天这题调了一天太累了,就没继续优化,过几天继续优化!!!!!!!)

<pre name="code" class="cpp">#include<iostream> 
#include<Cstdio>
using namespace std; 
int visit[100]; int visit1[100];
int map[100][100];
int nodeSize, caseSize,seq[100], Count;
bool Find(int num)
{
	int i;
	bool flag = true;
	
	for(i = 0; i < nodeSize; i++)
	{
		if(map[i][num] == 0)
			continue;
		flag = false;
		break;
	}
	return flag;
}

bool Check(int num)
{
	int i; bool flag = true;
	for(i = 0; i < nodeSize; i++)
	{
		if(map[i][num] == 0 || visit[i] == 1)
			continue;
		flag = false;
		break;
	}
	return flag;
}

bool topo(int node)
{
	int i;
	visit[node] = 1;
	seq[Count++] = node;
	for(i = 0; i < nodeSize; i++)
	{
		if(map[node][i] == 1 && visit[i] == 0
		   && Check(i))
			return topo(i);
	}
	return true;
}

bool dfs(int node)
{
	int i; visit[node] = 1;
	for(i = 0; i < nodeSize; i++)
	{
		if(map[node][i] == 1 && visit[i] == 0)
		{
			 if(dfs(i) == false)
			 {
				 visit[node] = 0;
				 return false;
			 }
		}
		else if(map[node][i] == 1 && visit[i] == 1)
		{
			visit[node] = 0;
			return false;
		}
	}
	visit[node] = 0;
	return true;
}

int main()  
{ 
	int i, j, k;
	int node1, node2;
	bool flag;
	char word[5];
	int result, num, num1;
	while(1)
	{
		scanf("%d%d", &nodeSize, &caseSize);
		if(nodeSize == 0 && caseSize == 0)
			break;
		flag = true; 
		for(i = 0; i < nodeSize; i++)
		{
			for(j = 0; j < nodeSize; j++)
			{
				map[i][j] = 0;
			}
		}
		flag = true; num = 0; result = 0, num1 = 0;

		for(i = 0; i < caseSize;i++)
		{
			scanf("%s", word);
			node1 = word[0] - 'A'; node2 = word[2] - 'A';
			map[node1][node2] = 1;
			

			for(k = 0; k < nodeSize; k++)
				visit[k] = 0;
			if(flag)
			{
			for(j = 0; j < nodeSize; j++)
			{
				if(flag && Find(j))
				{
					Count = 0;
					flag = topo(j);
					//cout << j << " " <<flag << endl;
					if(num == 0 && flag && Count == nodeSize)
					{
						result = i; num = 1;
					}
				}
			}
			}
			
			for(k = 0; k < nodeSize; k++)
				visit1[k] = 0;
			
			for(j = 0; j < nodeSize; j++)
			{
				if(result == 0 && num1 == 0 && !visit[j])
				{
					
					flag = dfs(j);
					if(flag == false)
					{
						result = i;
						num1 = 1;
						break;
					}
				}
			}
			
			
		}

		//dfs(0);
		if(!flag)
			printf("Inconsistency found after %d relations.\n", result + 1);
		else if(flag && result == 0)
			printf("Sorted sequence cannot be determined.\n");
		else
		{
			printf("Sorted sequence determined after %d relations: ", result + 1);
			for(i = 0; i < nodeSize; i++)
				printf("%c", 'A' + seq[i]);
			printf(".\n");
		}
		
	}
	return 0;
} 


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值