1. 程式人生 > >題目序號配給 字典序最小的拓撲排序

題目序號配給 字典序最小的拓撲排序

來源:長沙理工大學2018區域賽個人選拔賽1

題目:

描述: 在一種競賽中,題目往往是成套出現的。一道基礎題,稍加改動就會使難度上升幾個檔次。 現在有n道題目,編號為1~n;給出了m個二元組,每個二元組<a,b>表示 b題目是a題目的加強版,每個題目可能會有多個加強版,加強版的題目也可能會有加強版。 現在要將這n道題目放組成一場比賽,出於人文關懷方面的考慮,一道題目的簡單版本必須放在其所有加強版的前面。 例如ba的加強版,cb的加強版 那麼c在比賽中的題號必須大於ab的題號,b的題號也必須大於a的題號 你需要做得,是輸出一個長度為n的序列A

A[i] 表示編號為i的題目在比賽中的題號。 符合要求的答案很多,出題人並不想寫spj,所以請輸出字典序最小的方案。

輸入: 第一行為兩個數n,m表示有n道題,m個二元組(n,m≤106n,m \leq 10^6n,m≤106) 接下來有m行,每行有兩個數a,b 表示 題目b是題目a的加強版(1≤a,b≤n1 \leq a,b \leq n1≤a,b≤n)。 輸入保證有解

輸出: 按順序輸出每道題在比賽中的題號,要求字典序最小。 樣例輸入: 5 10 5 2 4 1 2 1 3 4 2 4 3 2 5 4 3 5 3 1 5 1 樣例輸出: 5 3 1 4 2

題解:

套一個字典序最小的拓撲排序模板就好了

AC程式碼:

#include <bits/stdc++.h>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
using namespace std;
/********************拓撲排序+佇列實現****************************/
const int maxv = 1e6 + 10;
const int maxe = 1e6 + 10;
struct Edge {
    int
to, val, next; } edge[maxe]; int head[maxe], in[maxe], cnt, TPOindex, TPOQueue[maxv], ans[maxv]; int n, m; priority_queue<int, vector<int>, greater<int> > pqi; void Topsort() { for (int i = 1 ; i <= n ; i++) { if (in[i] == 0) { pqi.push(i); } } while (!pqi.empty()) { int cur = pqi.top(); pqi.pop(); TPOQueue[TPOindex++] = cur; for (int i = head[cur]; i != -1; i = edge[i].next) { in[edge[i].to]--; if (in[edge[i].to] == 0) pqi.push(edge[i].to); } } } void addedge(int from, int to) { TPOindex = 0; edge[cnt].to = to; edge[cnt].next = head[from]; head[from] = cnt++; } void init() { cnt = 0; memset(head, -1, sizeof head); memset(in, 0, sizeof in); } /********************拓撲排序+佇列實現****************************/ int main(void) { init(); int t1, t2; scanf("%d%d", &n, &m); for (int i = 0; i < m; i++) { scanf("%d%d", &t1, &t2); addedge(t1, t2); in[t2]++; } Topsort(); int index = 1; for (int i = 0; i < TPOindex; i++) ans[TPOQueue[i]] = index++; for (int i = 1; i <= n; i++) printf("%d%c", ans[i], i == n ? '\n' : ' '); return 0; }