P3243 [HNOI2015] dish making

Posted by DWaller10 on Thu, 27 Jan 2022 04:28:29 +0100

Problem surface

Well known gourmet Xiao A was invited to ATM hotel to taste the dishes. ATM hotel has prepared \ (n \) dishes for Xiao A. the hotel numbers the dishes in the order of \ (1 \) to \ (n \) according to the estimated quality from high to low, and the estimated number of dishes with the highest quality is \ (1 \).

Due to the problem of taste matching between dishes, some dishes must be prepared before others. Specifically, there are \ (m \) bars. For example, the restriction that dish No. (i \) must be prepared before dish No. (j \) is abbreviated as \ ((i,j) \).

Now, the hotel hopes to find out the best order of making dishes, so that Xiao A can try to eat high-quality dishes first:

in other words,

  1. On the premise that all restrictions are met, dish \ (1 \) shall be made first as far as possible.

  2. Under the premise of meeting all restrictions and giving priority to the preparation of dishes \ (1 \), dishes \ (2 \) should be made as much as possible.

  3. Under the premise of meeting all restrictions and giving priority to dishes \ (1 \) and \ (2 \), dishes \ (3 \) should be made as much as possible.

  4. On the premise that all restrictions are met and dishes \ (1 \) and \ (2 \) and \ (3 \) are given priority, dishes \ (4 \) are given priority.

  5. and so on.

Example 1: there are \ (4 \) dishes in total, and there are two restrictions \ ((3,1) \), \ ((4,1) \), so the production order is \ (3,4,1,2 \).

Example 2: there are \ (5 \) dishes in total, and there are two restrictions \ ((5,2) \), \ ((4,3) \), so the production order is \ (1,5,2,4,3 \).

In example 1, first consider \ (1 \), because there are restrictions on \ ((3,1) \) and \ ((4,1) \), so \ (1 \) can be made only after \ (3 \) and \ (4 \) are made. According to 3, \ (3 \) should take precedence over \ (4 \) as far as possible, so it can be determined that the order of making the first three dishes is \ (3,4,1 \); Next, consider \ (2 \) and determine that the final production order is \ (3,4,1,2 \).

In example \ (2 \), making \ (1 \) first does not violate the restrictions; Next, when considering \ (2 \), there is a limit of \ ((5,2) \), so next, make \ (5 \) first and then \ (2 \); Next, when considering \ (3 \), there is a limit of \ ((4,3) \), so next, make \ (4 \) and then \ (3 \), so the final order is \ (1,5,2,4,3 \). Now you need to find out the optimal cooking order. No solution output is Impossible! (the first letter is uppercase, and the other letters are lowercase)

analysis

If cooking becomes a directed acyclic graph (DAG), then it is Impossible! The situation is that there is a closed loop, not DAG.

What about the rest? How to sort by topology? Set the dishes with small number as \ (a \) and the dishes with large number as \ (b \). We want \ (a \) to move forward as much as possible, but greed is easy to cite counter examples, which is not good. In another direction, let \ (b \) lean back as far as possible. No matter where \ (b \) is, we ensure that \ (a \) is in front, so we need to run the topology in the opposite direction. Connect \ (b \) to \ (a \) and run the topology of the inverse graph.

Reference code

#include<bits/stdc++.h>
#define cclear(x) memset((x),0,sizeof((x)))
#define final const
using namespace std;

const int MAXN = (1e5+5);
int n,m,cnt;
int indeg[MAXN],ans[MAXN];
vector<int> edge[MAXN];

inline void toposort(){
	priority_queue<int> pq;
	//Initialization of large root heap 
	for(int i=1;i<=n;i++){
		if(!indeg[i]){
			pq.push(i);
		}
	}
	while(!pq.empty()){
		final int tmp=pq.top();
		pq.pop();
		ans[++cnt]=tmp;
		for(int it:edge[tmp]){
			indeg[it]--;
			if(!indeg[it]){
				pq.push(it);
			}
		}
	}
}

int main(){
	int t;
	cin>>t;
	while(t--){
		// Clear residual data 
		cnt=0;
		cclear(ans);
		cclear(indeg);
		for(int i=1;i<=n;i++){
			edge[i].clear();
		}
		cin>>n>>m;
		for(int i=1,x,y;i<=m;i++){
			cin>>x>>y;
			edge[y].push_back(x); // Reverse mapping
			indeg[x]++; 
		}
		// Run through topology sorting
		toposort(); 
		if(cnt<n){
			cout<<"Impossible!";
		}
		else{
			for(int i=n;i>=1;i--){
				// Reverse mapping, of course, should be output in reverse order
				cout<<ans[i]<<' '; 
			}
		}
		cout<<endl;
	}
	return 0;
}

Acknowledge

reference material:

Topics: Graph Theory OI