ZCMU 1740: 关系推断

Description

给你一些已经确定的元素之间的关系,请你判断是否能从这些元素关系中推断出其他的元素关系。

Input

输入的第一行是一个整数N,表示测试数据的组数。
每组输入首先是一个正整数m(m<=100),表示给定元素关系的个数。
接下来m行,每行一个元素关系,格式为:
元素1<元素2  或者  元素1>元素2
元素用一个大写字母表示,输入中不会包含冲突的关系。

Output

对于每组输入,第一行输出“Case d:”,d是测试数据的序号,从1开始。
接下来输出所有推断出的新的元素关系,按照字典序从小到大排序,格式为:
元素1<元素2
每个元素关系占一行,输入中给定的元素关系不要输出。
如果没有新的元素关系推断出来,则输出NONE。

Sample Input

2 3 A<B C>B C<D 2 A<B C<D

Sample Output

Case 1: A<C A<D B<D Case 2: NONE

学校测试的一道题目,当时没学拓扑,表示一脸懵逼(参考了一下他人的组织方法)........拓扑排序的应用,中间用bfs搜一下所有<的点,用pair类型的vector保存一下这些点,本以为用优先队列就可以不用排序了,但还是要排序。。。。

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
set<int> s;
int vis[30][30];
vector<int> v[30];
vector<int> ans1;
vector<P> ans2;
int in[30];
void bfs(int p)
{
	queue<int> q;
	q.push(p);
	while(!q.empty())
	{
		int k=q.front();q.pop();
		for(int i=0;i<v[k].size();i++)
		{
			int y=v[k][i];
			ans1.push_back(y);
			q.push(y);
		}
	}
}
int main()
{
	int t;
	cin>>t;
	int cnt=0;
	while(t--)
	{
		memset(vis,0,sizeof(vis));
		memset(in,0,sizeof(in));
		s.clear();
		ans2.clear();
		for(int i=0;i<26;i++)
		v[i].clear();
		cnt++;
		int n;
		cin>>n;
		char str[3];
		while(n--)
		{
			cin>>str;
			s.insert(str[0]-'A');
			s.insert(str[2]-'A');
			vis[str[0]-'A'][str[2]-'A']=1;
			vis[str[2]-'A'][str[0]-'A']=1;
			if(str[1]=='<')
			{
				in[str[2]-'A']++;
				v[str[0]-'A'].push_back(str[2]-'A');
			}
			else
			{
				in[str[0]-'A']++;
				v[str[2]-'A'].push_back(str[0]-'A');
			}
		}
		priority_queue<int,vector<int>,greater<int> > q;
		for(int i=0;i<26;i++)
		{
			if(in[i]==0&&s.count(i))
			q.push(i); 
		}
		while(!q.empty())
		{
			int p=q.top();q.pop();
			ans1.clear();
			bfs(p);
			for(int i=0;i<ans1.size();i++)
			{
				int y=ans1[i];
				if(!vis[p][y])
				{
					vis[p][y]=1;
					vis[y][p]=1;
					ans2.push_back(P(p,y));
				}
			}
			for(int i=0;i<v[p].size();i++)
			{
				int k=v[p][i];
				in[k]--;
				if(in[k]==0&&s.count(k))
				{
					q.push(k);
				}
			}
		}
		printf("Case %d:\n",cnt);
		if(ans2.size()==0)
		cout<<"NONE"<<endl;
		else
		{
			sort(ans2.begin(),ans2.end());
			for(int i=0;i<ans2.size();i++)
			{
				printf("%c<%c\n",ans2[i].first+'A',ans2[i].second+'A');
			}
		}
	}
	return 0;
 } 
 
 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值