2019 ICPC Malaysia National J.Kitchen Plates

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

发布了78 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Fiveneves/article/details/104304793