【Best Coder】#35 DZY Loves Topological Sorting(线段树维护)

来源:互联网 发布:知乎日报mac 百度网盘 编辑:程序博客网 时间:2024/05/18 00:25

题目思路:题目要求点数最大的优先输出。由于可以将k条边去掉。

所以这边的一个基本思想就是。面对这次的输出。我们应该选择一个点数最大的,并且他的入度<=k即可。

并且注意是每次。每次都得重新选择。

下面这组数组就会让你懂得

5 3 2

4 5 

3 5

1 5

答案应该是 4 5 3 2 1

所以这边需要实时更新每个点的入度,并且每次选择最大的那个入度小于k的那个点,正好利用线段树的维护和查询功能

AC代码:

#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAX 100005#define ls rt<<1#define rs ls|1#define m (l+r)>>1int sum[MAX << 2];int head[MAX];int in[MAX];int cnt = 0;int ans[100005];struct pos{int v, next;}p[MAX];void addedge(int u, int v){p[cnt].v = v;p[cnt].next = head[u];head[u] = cnt++;}void uprt(int rt){sum[rt] = min(sum[ls], sum[rs]);}void build(int l, int r,int rt){if (l == r){sum[rt] = in[l];return;}int mid = m;build(l, mid, ls);build(mid + 1, r, rs);uprt(rt);}void updata(int q, int val,int l, int r, int rt){if (l == r){sum[rt] = val;return;}int mid = m;if (q<=mid)updata(q, val, l, mid, ls);elseupdata(q, val, mid + 1, r, rs);uprt(rt);}int get(int val, int l, int r, int rt){if (l == r)return l;int mid = m;if (val >=sum[rs])return get(val, mid + 1, r, rs);return get(val, l, mid, ls);}int main(){int n, k, q; while (~scanf("%d%d%d", &n, &k, &q)){memset(head, -1, sizeof(head));memset(in, 0, sizeof(in));cnt = 0;int a, b;while (k--){scanf("%d%d", &a, &b);addedge(a, b);in[b]++;}build(1, n, 1);for (int i = 0; i < n; i++){int res = get(q, 1, n, 1);ans[i] = res;q-= in[res];in[res] = 0x7ffffff;updata(res, in[res], 1, n, 1);for (int i = head[res]; i != -1; i = p[i].next){in[p[i].v]--;updata(p[i].v, in[p[i].v], 1, n, 1);}}printf("%d", ans[0]);for (int i = 1; i < n; i++)printf(" %d", ans[i]);puts("");}}

0 0