HDOJ5695 Gym Class ----- 拓扑排序

题目链接:https://vjudge.net/problem/HDU-5695

题意:n个人排成一列,编号为1-N,每个人的分数=min(排他前面人的编号),给定m个排斥条件,即A不允许B排在A前面,求分数和的最大值。

题解: 参考 http://www.bubuko.com/infodetail-2686140.html?__cf_chl_jschl_tk__=19fab1c4836ffc040f59b2980b97dabaaaae90f9-1589790195-0-AUPfZTvphgafKWPcLb2837cSF0vw0clI8pUTNAZKra1yagJELFv-3gwy1SRQYpUS5Biiu3Mf6hft1rGMHAYuavfT_gMo6lJOJ2QpFZF3LSm2ffmmFW-4kQsVoU5zrpiB7mgw5Cb6Jt5dv4bbsQSgHUzr4OuvZp2lvErjpT6SnykU6C01r2udaA1cHz0MSpfX9T7HBhAeBOD3CpIwpK_-AtvdjSbMy8SW5JRabpVXiegFV7IbFoM8tFtwY3RZ--oTMFG0ZVLhHzvCyXM3nlaCVnuudMgy1Bka09RJRs4abqJwXORDveS62ErIQ-xky-KX_w

不难想到贪心,每次取分数最大的排即可,但是因为有排斥条件,所以可以采用拓扑排序,图里面A->B表示A必须在B前面。。

#include 
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
vector vec[maxn];
priority_queue q;
int n, m;
int minid;
int indeg[maxn];
ll sum;

void topsort() {
    while(!q.empty()) q.pop();
    for(int i = 1;i <= n;i++) {
        if(!indeg[i]) q.push(i);
    }
    bool flag = false;
    while(!q.empty()) {
        int now = q.top();
        q.pop();
        if(!flag) {
            minid = now;
            flag = true;
        }
        minid = min(minid, now);
        sum += minid;
        for(int i = 0;i < vec[now].size();i++) {
            if(--indeg[vec[now][i]] == 0) q.push(vec[now][i]);
        }
    }
}


int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        sum = 0;
        memset(indeg, 0, sizeof indeg);
        for(int i = 0;i <= n;i++) vec[i].clear();
        while(m--) {
            int a, b;
            scanf("%d%d", &a,&b);
            vec[a].push_back(b);
            indeg[b]++;
        }
        topsort();
        printf("%lld\n", sum);
    }
    
    
    return 0;
}

 

你可能感兴趣的:(图论)