題目序號配給 字典序最小的拓撲排序
阿新 • • 發佈:2018-12-08
來源:長沙理工大學2018區域賽個人選拔賽1
題目:
描述: 在一種競賽中,題目往往是成套出現的。一道基礎題,稍加改動就會使難度上升幾個檔次。 現在有n道題目,編號為1~n;給出了m個二元組,每個二元組表示 b題目是a題目的加強版,每個題目可能會有多個加強版,加強版的題目也可能會有加強版。 現在要將這n道題目放組成一場比賽,出於人文關懷方面的考慮,一道題目的簡單版本必須放在其所有加強版的前面。 例如b是a的加強版,c是b的加強版 那麼c在比賽中的題號必須大於a和b的題號,b的題號也必須大於a的題號 你需要做得,是輸出一個長度為n的序列A
輸入: 第一行為兩個數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;
}