J.Kitchen Plates
题目链接-Kitchen Plates
You are given 5 different sizes of kitchen plates. Each plate is marked with a letter A, B, C, D, or E. You are given 5 statements comparing two different plates, you need to rearrange the plates from smallest size to biggest size. For example: the sizes of these plates.
题目大意
五个盘子A,B,C,D,E,给你五组每两个盘子之间的大小关系,将这五个盘子从大到小排列,如果五个盘子大小关系存在矛盾,就输出impossible
解题思路
连边+拓扑排序
- 因为输入并没有保证一定可以确定每两个盘子之间的大小关系,无法准确确定大小关系,所以可用拓扑排序
- 先统计所有节点的入度,对于入度为0的节点就可以分离出来,即将所有入度为0的顶点放入队列,然后把这个节点指向的节点的入度减1,直到所有的节点都被分离出来。如果最后不存在入度为0的节点,那就说明有环,不存在拓扑排序
详细解析见代码
对拓扑排序不太熟悉的可以看看这道题AcWing-848. 有向图的拓扑序列
- 伪代码
附上代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e5+5;
const int M=1e9+7;
typedef long long ll;
typedef pair<int,int> PII;
map<char,int> mp;//字母与数字的转换
vector<int> v;
char a[5]={'A','B','C','D','E'};
int b[10];//表示每个点的入度
bool dir[6][6];
priority_queue<int,vector<int>,greater<int> >q;//从小到大的优先队列
void topsort(){
for(int i=0;i<5;i++){
if(b[i]==0)
q.push(i);//将所有入度为0的顶点放入队列
}
while(!q.empty()){
int x=q.top();
q.pop();//选一个入度为0的点出队列
v.push_back(x);
for(int i=0;i<5;i++){//删除所有与x顶点有关的边
if(dir[x][i]){//遍历当前点能到的所有点,能到的入度都减去1
b[i]--;//邻接点入度减一
if(!b[i])
q.push(i);
}
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
mp['A']=0;
mp['B']=1;
mp['C']=2;
mp['D']=3;
mp['E']=4;
int t=5;
while(t--){
string s;
cin>>s;
if(s[1]=='<')
swap(s[0],s[2]);
b[mp[s[2]]]++;
dir[mp[s[0]]][mp[s[2]]]=1;//连边构图
}
topsort();
if(v.size()<5){
cout<<"impossible"<<endl;
return 0;
}
for(int i=4;i>=0;i--)
cout<<a[v[i]];
cout<<endl;
return 0;
}