P3243 [HNOI2015] food production topological sorting

Title Description

A little-known chefs are invited to ATM Hotel for its tasting menu. A small hotel ATM prepared for the N dish, according to the quality of the hotel as dishes from high to low given the estimated 1 to N sequence number, the highest estimated number 1 quality cuisine.

Due to problems with taste between dishes, some dishes must be made before the other dishes. Specifically, a total of M strip such as "i No. dishes 'must' before the j number of dishes made" limited, so we will limit abbreviated as <i, j>.

Now, the hotel hoping to find an optimal production sequence of dishes, the small A can try to eat high quality dishes:

In other words,

(1) In all the prerequisites of limitation, the dishes 1 "possible" priority production;

(2) meet all restrictions, dishes 1 "try" preferentially made under the premise, No. 2 dishes "try" priority production;

(3) "try" lower priority context, No. 3 dishes "try" priority fabricated to meet all restrictions, No. 1 and No. 2 dishes

; (4) meet all restrictions, No. 1 and No. 2 and No. 3 dishes "try" lower priority context, 4 dishes "try" priority production;

(5) and so on.

Example 1: A total of four dishes, two limit <3,1>, <4,1>, the production sequence is 3,4,1,2.

Example 2: A total of five dishes, two limit <5,2>, <4,3>, the production order is 1,5,2,4,3.

Example 1, the first consideration 1, because there is a limit <3,1> and <4,1>, so in order to make a finished production after only 3 and 4, and according to (3), and No. 3 should "try" to 4 priority number, so the current can be determined three-course production order is 3,4,1; 2 next consider, determine the final production order is 3,4,1,2.

In Example 2, first, a limitation is not contrary; next consider when 2 <5,2> limited, so the next 5 to create remanufacturing 2; 3 next consider with a <4,3> restriction , so the next 3 to produce 4 remanufacturing, it is ultimately the order 1,5,2,4,3. Now you need to find the best dishes making the order. No solution output "Impossible!" (Without the quotation marks, the first letter capitalized, remaining letters lowercase)

Input Format

The first line is a positive integer D, represents the number of data sets. Next, the group D data. For each set of data: The first line of two space-separated positive integers N and M, respectively, represents the number of dishes and the number of entries in the order of production limitations. Next M rows, each row two positive integers x, y, represents the limit "x to y must No. No. dishes dish-making". (Note: there may be the same as the M restriction limits)

Output Format

D output file contains only lines of N integers, represents the optimal production sequence of dishes, or "Impossible!" Indicates no solution (without the quotes).

Entry
3
5 4
5 4
5 3
4 2
3 2
3 3
1 2
2 3
3 1
5 2
5 2
4 3
Export
1 5 3 4 2 
Impossible! 
1 5 2 4 3

Description / Tips

Sample [explain]

While the second set of data prior to claim 1 dishes 2 dishes prepared dishes 2 dishes prior to the production of 3, 3 before the dishes

Dishes 1 production, which is in any case impossible to meet, resulting in no solution.

100% of the data satisfies N, M <= 100000, D <= 3.

answer:

Impossible situation: if and only when there is a closed loop.

②设编号小的菜为,编号大的菜为b。我们想要a尽量往前靠,贪心很容易举出反例

  如:4种菜肴,限制为<2,4><3,1>那么字典序最小的是2,3,1,4,但题目要求的最优解是3,1,2,4

③如果最后一个数字在合法范围内尽可能大,那么这样是绝对有利的。

因为如果设最后一个数字是x,那么除了x之外的所有数都不会被放到最后一个位置。

  因此,最优解就是符合条件的排列中,反序列的字典序最大的排列。

反向跑拓扑。让b连向a,跑反图的拓扑。利用优先队列维护。

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int N = 1e5 + 5;
int n, m, cnt, T, indeg[N], ans[N];
vector <int> edge[N];
void input() {
    cin >> n >> m;
    for(int i = 1, x, y;i <= m;i ++) {
        cin >> x >> y;
        edge[y].push_back(x); indeg[x] ++;
    }
}
void topsort() {
    priority_queue <int> q;
    for(int i = 1;i <= n;i ++)
    if(! indeg[i]) q.push(i);
    while(! q.empty()) {
        int tmp=q.top(); q.pop();
        ans[++ cnt] = tmp;
//       for(vector<int>::iterator it = edge[tmp].begin();it != edge[tmp].end();it ++) {
//           indeg[*it]--;                            //迭代器大法好啊!! 
//           if(! indeg[*it]) q.push(*it);
//        }
        for(int i = 0;i < edge[tmp].size();i ++) {
            int it = edge[tmp][i]; indeg[it] --;
            if(! indeg[it]) q.push(it);
        }
    }
}
void output() {
    if(cnt < n) { puts("Impossible!"); return; }
    for(int i = n; i ;i --) cout << ans[i] << " "; cout << endl;
}
void clear() {
    cnt = 0;
    memset(ans, 0, sizeof(ans));
    memset(indeg, 0, sizeof(indeg));
    for(int i = 1;i <= n;i ++) edge[i].clear();
}
int main() {
    cin >> T;
    while(T --> 0) clear(), input(), topsort(), output();
    //一时压行一时爽,一直压行一直爽~~~ 
    return 0;
}

 

 

 

Guess you like

Origin www.cnblogs.com/Paranoid-LS/p/11246986.html