hdu 5195(拓扑排序+线段树优化)

来源:互联网 发布:linux which命令 编辑:程序博客网 时间:2024/06/11 12:34

DZY Loves Topological Sorting

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1064    Accepted Submission(s): 327


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 v,u 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 mostk 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).

解题思路:

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

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<set>using namespace std;const int maxn = 100005;const int inf = 0x3f3f3f3f;struct Seg {int l,r,Min; //Min表示在区间[l,r]上的最小入度}tree[maxn<<2];struct Edge {int to,next;}edge[maxn];int n,m,k,cnt,head[maxn];int ind[maxn],res[maxn];void addedge(int u,int v) {edge[cnt].to = v;edge[cnt].next = head[u];head[u] = cnt++;}void build(int rt,int l,int r) {tree[rt].l = l, tree[rt].r = r;if(tree[rt].l == tree[rt].r) {tree[rt].Min = ind[l];return;}int mid = (l + r) >> 1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);tree[rt].Min = min(tree[rt<<1].Min,tree[rt<<1|1].Min);}void update(int rt,int pos) {if(tree[rt].l == tree[rt].r) {tree[rt].Min--;return;}int mid = (tree[rt].l + tree[rt].r) >> 1;if(pos <= mid)update(rt<<1,pos);else update(rt<<1|1,pos);tree[rt].Min = min(tree[rt<<1].Min,tree[rt<<1|1].Min);}int query(int rt,int k) {if(tree[rt].l == tree[rt].r) {tree[rt].Min = inf;return tree[rt].l;}int ans;if(tree[rt<<1|1].Min <= k) ans = query(rt<<1|1,k);else ans = query(rt<<1,k);tree[rt].Min = min(tree[rt<<1].Min,tree[rt<<1|1].Min);return ans;}int main() {int u,v;while(scanf("%d%d%d",&n,&m,&k)!=EOF) {cnt = 0;memset(head,-1,sizeof(head));memset(ind,0,sizeof(ind));for(int i = 1; i <= m; i++){scanf("%d%d",&u,&v);addedge(u,v);ind[v]++;}build(1,1,n);for(int i = 1; i <= n; i++) {int u = query(1,k);printf(i==n?"%d\n":"%d ",u);k -= ind[u];ind[u] = 0;for(int j = head[u]; j != -1; j = edge[j].next) {int v = edge[j].to;if(ind[v] > 0) {ind[v]--;update(1,v);}}}}return 0;}


0 0
原创粉丝点击