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;
}