• gym 100801G.Graph(拓扑排序,贪心构造)


    gym 100801G

    题意:

    给出 (n) 个点 (m) 条边的 (DAG),要求最多加 (k) 条有向边(不能形成环),使得可能的字典序最小的拓扑序列最大。输出最终最小的拓扑序列,以及加边数,加的边((1 leq n leq 10^5,0 leq m leq 10^5))

    题解:

    用两个优先队列 (minQ,maxQ) ,一个是小元素在前,另一个是大元素在前,前一个维护当前入度为0的所有点,一个用来维护需要被加边的点,然后对于 (minQ) 中值最小的点,如果其中还有其他点且k还没用完,那么我们便直接把它扔进 (maxQ) 中待处理,这样就是让小的元素晚点拓扑出来;如果第 (minQ) 中只有这一个点,我们便考虑能不能从 (maxQ) 中找一个最大的点来代替它拓扑出去,然后不断迭代直到两个队列都为空。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<stack>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define pb push_back
    #define fi first
    #define se second
    #define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
    typedef vector<int> VI;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int inf=0x3fffffff;
    const ll mod=1000000007;
    const int maxn=1e5+10;
    int head[maxn];
    struct edge
    {
        int to,next;
    }e[maxn*2];   //
    int tol=0;
    void add(int u,int v)
    {
        e[++tol].to=v,e[tol].next=head[u],head[u]=tol;
    }
    priority_queue<int,vector<int>,greater<int> >minQ;
    priority_queue<int> maxQ;
    int d[maxn];
    int ans[maxn];
    vector<PII> res;
    void release(int u)
    {
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(--d[v]==0) minQ.push(v);
        }
    }
    
    int main()
    {
        freopen("graph.in","r",stdin);
        freopen("graph.out","w",stdout);
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        rep(i,1,m+1)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            d[v]++;
        }
        rep(i,1,n+1) if(!d[i]) minQ.push(i);
        int len=0;
        while(len<n)
        {
            len++;
            while(k&&minQ.size()>1)
            {
                k--;
                int t=minQ.top();
                minQ.pop();
                maxQ.push(t);
            }
            if(minQ.size()==0)
            {
                int t=maxQ.top();
                maxQ.pop();
                ans[len]=t;
                release(t);
                res.pb(make_pair(ans[len-1],t));
            }
            else if(minQ.size()==1&&k&&maxQ.size()&&minQ.top()<maxQ.top())
            {
                k--;
                int t=maxQ.top();
                maxQ.pop();
                maxQ.push(minQ.top());
                minQ.pop();
                ans[len]=t;
                release(t);
                res.pb(make_pair(ans[len-1],t));
            }
            else
            {
                int t=minQ.top();
                minQ.pop();
                ans[len]=t;
                release(t);
            }
        }
        rep(i,1,n+1) printf("%d ",ans[i]);
        puts("");
        printf("%d
    ",(int)res.size());
        for(auto it:res)
            printf("%d %d
    ",it.fi,it.se);
        return 0;
    }
    
    
  • 相关阅读:
    C# 获取文件名及扩展名
    Javscript调用iframe框架页面中函数的方法
    jquery事件重复绑定的几种解决方法 (二)
    Jquery 点击事件重复获取叠加 (一)
    .NET 即时通信,WebSocket服务端实例
    .Net ASP.NET 打开指定文件夹
    动态 hover 使用变相使用
    给 layui upload 带每个文件的进度条, .net 后台代码
    layui upload 后台获取不到值
    ECharts配置项之title(标题)
  • 原文地址:https://www.cnblogs.com/tarjan/p/7636038.html
Copyright © 2020-2023  润新知