zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    [置顶] windows player,wzplayerV2 for windows
    wzplayer 近期将会支持BlackBerry和WinPhone8
    wzplayerEx for android(真正硬解接口,支持加密的 player)
    ffmpeg for ios 交叉编译 (支持i686 armv7 armv7s) 包含lame支持
    ffmpeg for ios 交叉编译 (支持i686 armv7 armv7s) 包含lame支持
    编译cegcc 0.59.1
    wzplayer 近期将会支持BlackBerry和WinPhone8
    wzplayerEx for android(真正硬解接口,支持加密的 player)
    windows player,wzplayerV2 for windows(20140416)更新
    编译cegcc 0.59.1
  • 原文地址:https://www.cnblogs.com/fenice/p/5424673.html
Copyright © 2011-2022 走看看