码迷,mamicode.com
首页 > 其他好文 > 详细

Gym - 100801G: Graph (贪心+set+拓扑)(好题)

时间:2018-08-12 14:04:29      阅读:109      评论:0      收藏:0      [点我收藏+]

标签:ons   names   while   set   queue   第一个   ace   思路   col   

题意:给定一个N点M边的有向图,叫你加最多K条边,使得最小拓扑序最大.

思路:不是那么简单的题.  参照了别人的代码,最后想通了.

贪心原则: 用两个单调队列维护, 第一个序列S1单增, 表示当前入度为0的点 ; 第二个序列S2单减,表示需要加边的点.

如果S1的最大值大于S2的最大值,则对其加边.

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
priority_queue<int>p;
priority_queue<int,vector<int>,greater<int> >q;
vector<int>G[maxn];
int cnt,ind[maxn];
int num,used,ans[maxn],a[maxn],b[maxn];
void del(int v){
    ans[++num]=v;
    for(int i=0;i<G[v].size();i++) if(!--ind[G[v][i]]) q.push(G[v][i]);
    if(q.empty()){
        if(!p.empty()){
            int c=p.top(); p.pop();
            G[ans[num]].push_back(c);
            a[++used]=ans[num]; b[used]=c;
            del(c);
        }
    }
}
int main()
{
    int N,M,K,u,v,i,j;
    scanf("%d%d%d",&N,&M,&K);
    for(i=1;i<=M;i++){
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        ind[v]++;
    }
    for(i=1;i<=N;i++) if(!ind[i]) q.push(i);
    while(!q.empty()){
        if(K&&(q.size()>1||(!p.empty()&&q.top()<p.top()))){
            K--;
            int c=q.top(); p.push(c); q.pop();
            if(q.empty()){
                int c=p.top(); p.pop();
                G[ans[num]].push_back(c);
                a[++used]=ans[num]; b[used]=c;
                del(c);
            }    
        }
        else{
            int c=q.top(); q.pop();
            del(c);
        }
    }
    return 0; 
}

 

Gym - 100801G: Graph (贪心+set+拓扑)(好题)

标签:ons   names   while   set   queue   第一个   ace   思路   col   

原文地址:https://www.cnblogs.com/hua-dong/p/9462418.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!