HDU 5195 DZY Loves Topological Sorting

来源:互联网 发布:组态王软件价格 编辑:程序博客网 时间:2024/05/21 09:51
Problem Description
A topological sort or topological ordering of a directed graph is a linear ordering of its vertices such that for every directed edge (uv) from vertex u to vertex vu comes before v in the ordering.
Now, DZY has a directed acyclic graph(DAG). You should find the lexicographically largest topological ordering after erasing at most k edges from the graph.
 

Input
The input consists several test cases. (TestCase5)
The first line, three integers n,m,k(1n,m105,0km).
Each of the next m lines has two integers: u,v(uv,1u,vn), representing a direct edge(uv).
 

Output
For each test case, output the lexicographically largest topological ordering.
 

Sample Input
5 5 21 24 52 43 42 33 2 01 21 3
 

Sample Output
5 3 1 2 41 3 2
Hint
Case 1.Erase the edge (2->3),(4->5).And the lexicographically largest topological ordering is (5,3,1,2,4).

Problem B - DZY Loves Topological Sorting因为我们要求最后的拓扑序列字典序最大,所以一定要贪心地将标号越大的点越早入队。我们定义点i的入度为di。假设当前还能删去k条边,那么我们一定会把当前还没入队的dik的最大的i找出来,把它的di条入边都删掉,然后加入拓扑序列。可以证明,这一定是最优的。具体实现可以用线段树维护每个位置的di,在线段树上二分可以找到当前还没入队的dik的最大的i。于是时间复杂度就是O((n+m)logn).

正版的题解,不过我不是这样写的也过了,感觉还是我的简单。

记录每个点的入度,以及从小到大的边数(因为是字典序最大所以要删除的应该是那些从小到大的边)

然后从n到1把这些边尽量删除,用优先队列保存,然后输出拓扑序列。

#include<stdio.h>#include<iostream>#include<algorithm>#include<map>#include<queue>#include<stack>#include<vector>#include<cstdlib>#include<functional>using namespace std;const int maxn = 100005;int n, m, k, x, y, v[maxn], f, u[maxn];vector<int> tree[maxn];int main(){    while (scanf("%d%d%d", &n, &m, &k) != EOF)    {        memset(v, 0, sizeof(v));        memset(u, 0, sizeof(u));        for (int i = 0; i < m; i++)        {            scanf("%d%d", &x, &y);            tree[x].push_back(y);            if (x < y) v[y]++;            u[y]++;        }        priority_queue<int> p;        for (int i = n; i > 0; i--)            if (k >= v[i]) {                 k -= v[i], u[i] -= v[i];                 if (!u[i]) p.push(i);            }        f = 0;        while (!p.empty())        {            if (f) printf(" "); else f = 1;            int x = p.top();    p.pop();            printf("%d", x);            for (int i = 0; i < tree[x].size(); i++)            {                int y = tree[x][i];                u[y]--;                if (!u[y]) p.push(y);            }            tree[x].clear();        }        printf("\n");    }}
#include<stdio.h>#include<iostream>#include<algorithm>#include<map>#include<queue>#include<stack>#include<vector>#include<cstdlib>#include<functional>using namespace std;const int maxn = 100005;int n, m, k, x, y, v[maxn], u[maxn], f;vector<int> tree[maxn];int main(){while (scanf("%d%d%d", &n, &m, &k) != EOF){memset(v, 0, sizeof(v));memset(u, 0, sizeof(u));for (int i = 0; i < m; i++){scanf("%d%d", &x, &y);tree[x].push_back(y);v[y]++;}priority_queue<int> p;for (int i = n; i > 0; i--)if (k >= v[i]) p.push(i);f = 0;while (!p.empty()){int x = p.top();    p.pop();if (v[x] <= k&&!u[x]){k -= v[x]; v[x] = 0; u[x] = 1;if (f) printf(" "); else f = 1;printf("%d", x); for (int i = 0; i < tree[x].size(); i++){int y = tree[x][i];if (!(--v[y])) p.push(y);}tree[x].clear();}}printf("\n");}}
这样也是可以的。

0 0
原创粉丝点击