zoukankan      html  css  js  c++  java
  • HDU 5638 Toposort 线段树+贪心

    题意:bc round 74

    分析:

    参考下普通的用堆维护求字典序最小拓扑序, 用某种数据结构维护入度小于等于k的所有点, 每次找出编号最小的, 并相应的减少k即可.

    这个数据结构可以用线段树, 建立一个线段树每个节点[l,r]维护编号从ll到rr的所有节点的最小入度, 查询的时候只需要在线段树上二分,

    找到最小的x满足入度小于等于k.

    复杂度O((n+m)logn)

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <queue>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const int mod=1e9+7;
    const int INF=0x3f3f3f3f;
    const int N=1e5+5;
    int d[N],o[N<<2],head[N],p;
    struct Edge
    {
        int v,next;
    }edge[N*2];
    void add(int u,int v)
    {
        edge[p].v=v;
        edge[p].next=head[u];
        head[u]=p++;
    }
    void pushup(int rt)
    {
        o[rt]=min(o[rt*2],o[rt*2+1]);
    }
    void build(int rt,int l,int r)
    {
        if(l==r)
        {
            o[rt]=d[l];
            return;
        }
        int mid=(l+r)>>1;
        build(rt*2,l,mid);
        build(rt*2+1,mid+1,r);
        pushup(rt);
    }
    void update(int rt,int l,int r,int pos)
    {
        if(l==r)
        {
            o[rt]=d[l];
            return;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)update(rt*2,l,mid,pos);
        else update(rt*2+1,mid+1,r,pos);
        pushup(rt);
    }
    int query(int rt,int l,int r,int c)
    {
       if(l==r)
         return l;
       int mid=(l+r)>>1;
       if(o[rt*2]<=c)return query(rt*2,l,mid,c);
       else return query(rt*2+1,mid+1,r,c);
    }
    int main()
    {
        int T,n,m,k;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d%d%d",&n,&m,&k);
            memset(head,-1,sizeof(head));
            memset(d,0,sizeof(d));
            p=0;
            for(int i=0;i<m;++i)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                add(u,v);
                ++d[v];
            }
            build(1,1,n);
            LL ans=0;
            for(int i=1;i<=n;++i)
            {
                LL x=query(1,1,n,k),y=i;
                ans=(ans+x*y%mod)%mod;
                k-=d[x];
                d[x]=INF;
                update(1,1,n,x);
                for(int j=head[x];~j;j=edge[j].next)
                {
                   int v=edge[j].v;
                   if(d[v]==INF)continue;
                   --d[v];
                   update(1,1,n,v);
                }
            }
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    .Net程序破解
    SyntaxHighlighter插件测试
    Executing SQL using an ArcSDE connection
    VisualSVN增加密码php修改页面
    SyntaxHighlighter插件测试
    Executing SQL using an ArcSDE connection
    VisualSVN增加密码php修改页面
    FreeTextBox增加表情和代码着色功能
    找到了一篇用户角色处理的好文章
    男人25岁前的忠告
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5246748.html
Copyright © 2011-2022 走看看