• HDU 5195 DZY Loves Topological Sorting 拓扑排序


    题目链接:

    hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5195

    bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=573&pid=1002

    题解:

    1、拓扑排序+贪心

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<queue>
     7 using namespace std;
     8 
     9 const int maxn = 1e5 + 10;
    10 const int INF = 0x3f3f3f3f;
    11 
    12 int n, m, k;
    13 
    14 struct Node {
    15     int v, flag;
    16     Node(int v,int flag=0):v(v),flag(flag){}
    17     Node() { flag = 0; }
    18 };
    19 
    20 vector<Node> head[maxn];
    21 int ind[maxn],done[maxn];
    22 
    23 void init() {
    24     for (int i = 0; i < n; i++) {
    25         ind[i] = done[i]=0;
    26         head[i].clear();
    27     }
    28 }
    29 
    30 int main() {
    31     while (scanf("%d%d%d", &n, &m, &k) == 3 && n) {
    32         init();
    33         for (int i = 0; i < m; i++) {
    34             int u, v;
    35             scanf("%d%d", &u, &v); u--, v--;
    36             ind[v]++;
    37             head[u].push_back(Node(v,0));
    38         }
    39 
    40         priority_queue<int> pq;
    41 
    42         //删边
    43         for (int i = n - 1; i >= 0; i--) {
    44             if (k >= ind[i]) {
    45                 //将i的父亲ui中,满足ui<i,即边(ui,i)删了,这里要注意,对于边(ui,i),ui>i的边,根本不用删
    46                 k -= ind[i];
    47                 pq.push(i);
    48                 for (int j = 0; j < head[i].size(); j++) {
    49                     Node &nd = head[i][j];
    50                     if (i > nd.v) {
    51                         //把边(i,v)删了,拓扑排序的时候不能再走这条边了
    52                         nd.flag = 1;
    53                         ind[nd.v]--;
    54                     }
    55                 }
    56             }
    57         }
    58 
    59         vector<int> ans;
    60         //拓扑排序
    61         while (!pq.empty()) {
    62             int u = pq.top(); pq.pop();
    63             if (done[u]) continue;
    64             ans.push_back(u);
    65             done[u] = 1;
    66             for (int i = 0; i < head[u].size(); i++) {
    67                 Node& nd = head[u][i];
    68                 if (done[nd.v]||nd.flag) continue;
    69                 ind[nd.v]--;
    70                 if (ind[nd.v] == 0) pq.push(nd.v);
    71             }
    72         }
    73 
    74         printf("%d", ans[0]+1);
    75         for (int i = 1; i < ans.size(); i++) printf(" %d", ans[i]+1);
    76         printf("
    ");
    77     }
    78     return 0;
    79 }
    80 /*
    81 5 3 1
    82 4 3
    83 1 3
    84 3 2
    85 
    86 5 3 0
    87 4 3
    88 1 3
    89 3 2
    90 */

     2、线段树+贪心

    对于节点i,入度为ind[i],则可以这样贪心:对于1<=i<=n,求最大的i使得ind[i]<=k,我们可以把入度数组做成线段树,维护最小入度,二分查找,优先搜右边(右边的i会更大),找到以后,吧对于的子节点vj的入度减1,k-=ind[i]。这样一直做n次就能得到答案。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<vector>
     4 #include<algorithm>
     5 #define lson (o<<1)
     6 #define rson ((o<<1)+1)
     7 #define M (l+(r-l)/2)
     8 using namespace std;
     9 
    10 const int maxn = 1e5 + 10;
    11 const int INF = 0x3f3f3f3f;
    12 
    13 int n, m, k;
    14 
    15 vector<int> head[maxn];
    16 int ind[maxn<<2],minv[maxn<<2];
    17 
    18 int _pos, _v;
    19 void update(int o, int l, int r) {
    20     if (l==r) {
    21         ind[o] += _v;
    22         minv[o] = ind[o];
    23     }
    24     else {
    25         if (_pos <= M) update(lson, l, M);
    26         else update(rson, M + 1, r);
    27         minv[o] = min(minv[lson], minv[rson]);
    28     }
    29 }
    30 
    31 void query(int o, int l, int r,int &res) {
    32     if (l == r) {
    33         if (ind[o] <= k) {
    34             k -= ind[o];
    35             res = l;
    36         }
    37     }
    38     else {
    39         //printf("lson:%d,rson:%d
    ",minv[lson],minv[rson]);
    40         if (k >= minv[rson]) query(rson, M + 1, r,res);
    41         else if (k >= minv[lson]) query(lson, l, M,res);
    42     }
    43 }
    44 
    45 void init() {
    46     for (int i = 1; i <= n; i++) head[i].clear();
    47     memset(ind, 0, sizeof(ind));
    48     memset(minv,0,sizeof(minv));
    49 }
    50 
    51 int main() {
    52     while (scanf("%d%d%d", &n, &m, &k) == 3 && n) {
    53         init();
    54         for (int i = 0; i < m; i++) {
    55             int u, v;
    56             scanf("%d%d", &u, &v);
    57             head[u].push_back(v);
    58             _pos = v, _v = 1;
    59             update(1, 1, n);
    60         }
    61         //puts("after update");
    62         vector<int> ans;
    63         for (int i = 0; i < n; i++) {
    64             int res;
    65             query(1, 1, n, res);
    66             //puts("after first qurey!");
    67             //printf("res:%d
    ", res);
    68             ans.push_back(res);
    69             for (int j = 0; j < head[res].size(); j++) {
    70                 _pos = head[res][j], _v = -1;
    71                 update(1, 1, n);
    72                 //puts("after first upate");
    73             }
    74             _pos = res, _v = INF;
    75             update(1, 1, n);
    76         }
    77         //puts("ans is zero");
    78         printf("%d", ans[0]);
    79         for (int i = 1; i < ans.size(); i++) printf(" %d", ans[i]);
    80         printf("
    ");
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    Shell笔记——文本操作
    Shell笔记——加密命令
    conda,pip 安装指定版本的指定包
    如何检查tensorflow环境是否能正常调用GPU
    Windows10中使用Anaconda安装keras-gpu版本(遇到的坑)
    canvas一些属性
    块级元素,行内元素,行内块级元素都有哪些
    面向对象版Tab栏切换
    注册事件的兼容性处理
    常见的移动端问题
  • 原文地址:https://www.cnblogs.com/fenice/p/5424673.html
Copyright © 2020-2023  润新知