codeforces825E Minimal Labels【拓扑排序】

来源:互联网 发布:centos 删除目录 编辑:程序博客网 时间:2024/05/29 19:16

E. Minimal Labels

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a directed acyclic graph with n vertices and m edges. There are no self-loops or multiple edges between any pair of vertices. Graph can be disconnected.

You should assign labels to all vertices in such a way that:

Labels form a valid permutation of length n — an integer sequence such that each integer from 1 to n appears exactly once in it.
If there exists an edge from vertex v to vertex u then labelv should be smaller than labelu.
Permutation should be lexicographically smallest among all suitable.
Find such sequence of labels to satisfy all the conditions.

Input
The first line contains two integer numbers n, m (2 ≤ n ≤ 105, 1 ≤ m ≤ 105).

Next m lines contain two integer numbers v and u (1 ≤ v, u ≤ n, v ≠ u) — edges of the graph. Edges are directed, graph doesn’t contain loops or multiple edges.

Output
Print n numbers — lexicographically smallest correct permutation of labels of vertices.

Examples
input
3 3
1 2
1 3
3 2
output
1 3 2
input
4 5
3 1
4 1
2 3
3 4
2 4
output
4 1 2 3
input
5 4
3 1
2 1
2 3
4 5
output
3 1 2 4 5

题意:给出一个n个点,m条边的有向图,输出满足拓扑排序的字典序序列。

单纯的拓扑排序会存在很多个可行解,题目要求字典序。
字典序要求节点序号小的标签值尽可能小。一开始想的做法是用小根堆实现拓扑排序,在入度为0的点中选择序号最小的一次排列。但这样是错误的,混淆了“让靠前的尽量小”和“让小的尽量靠前”的关系。小根堆的实现方式,每次在入度为0的点钟选择序号最小的进行标签,但是这样无法保证字典序。
相反的,如果采用大根堆实现拓扑排序,利用出度去反向排列,这样能保证每次选择的是出度为0的点中序号最大的点,这样一层一层下去即能满足让靠前的尽量小,也能满足让小的尽量靠前。

#include<bits/stdc++.h>using namespace std;typedef long long LL;int n, m;struct node{    int d;    int number;    node(int d, int number) : d(d), number(number) {}    node() {}    friend bool operator < (const node& a, const node& b)    {        return a.number<b.number;    }} du[100005];vector<int> g[100005];int label[100005];priority_queue<node> q;int main(){    ios::sync_with_stdio(false);    while(cin >> n >> m)    {        int lab = n;        memset(du, 0, sizeof(du));        memset(g, 0, sizeof(g));        for(int i = 1; i <= n; ++i) du[i].number = i;        for(int i = 0; i < m; ++i)        {            int x, y;            cin >> x >> y;            du[x].d++;            g[y].push_back(x);        }        for(int i = 1; i <= n; ++i)        {            if(du[i].d == 0)                q.push(du[i]);        }        int cnt = n;        while(!q.empty())        {            node temp = q.top();            q.pop();            label[temp.number] = cnt--;            for(int i = 0; i < g[temp.number].size(); ++i)            {                int x = g[temp.number][i];                if(du[x].d)                {                    du[x].d--;                    if(du[x].d == 0) q.push(du[x]);                }            }        }        for(int i = 1; i <= n; ++i)            cout << label[i] << " ";    }    return 0;}
原创粉丝点击