HDU5695 拓扑排序

  附上题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5695

  

Problem Description
众所周知,度度熊喜欢各类体育活动。

今天,它终于当上了梦寐以求的体育课老师。第一次课上,它发现一个有趣的事情。在上课之前,所有同学要排成一列, 假设最开始每个人有一个唯一的ID,从1到N,在排好队之后,每个同学会找出包括自己在内的前方所有同学的最小ID,作为自己评价这堂课的分数。麻烦的是,有一些同学不希望某个(些)同学排在他(她)前面,在满足这个前提的情况下,新晋体育课老师——度度熊,希望最后的排队结果可以使得所有同学的评价分数和最大。
 

 

Input
第一行一个整数T,表示T(1T30) 组数据。

对于每组数据,第一行输入两个整数NM(1N100000,0M100000),分别表示总人数和某些同学的偏好。

接下来M行,每行两个整数A 和B(1A,BN),表示ID为A的同学不希望ID为B的同学排在他(她)之前。你可以认为题目保证至少有一种排列方法是符合所有要求的。
 

 

分析:根据同学之间的嫌弃信息, 我们可以建一个图, 然后让编号大的人尽可能排到前面即可。 可以使用优先队列来实现,注意会爆int, 代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 100000 + 100;
int N, M;
vector<int> G[maxn];
int indegree[maxn];

int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &N, &M);
        for(int i=1; i<=N; i++) {
            indegree[i] = 0;
            G[i].clear();
        }
        for(int i=0; i<M; i++) {
            int u,  v;
            scanf("%d%d",  &u, &v);
            G[u].push_back(v);
            indegree[v]++;
        }
        priority_queue<int> que;
        for(int i=1; i<=N; i++) if(!indegree[i]) que.push(i);
        long long res = 0;
        int rk = inf;
        while(!que.empty()) {
            int num = que.top(); que.pop();
            rk = min(rk, num);
            res += rk;
            for(int i=0; i<G[num].size(); i++) {
                int v = G[num][i];
                indegree[v]--;
                if(!indegree[v]) que.push(v);
            }
        }
        printf("%lld\n", res);
    }
    return 0;
}

 

 
posted @ 2016-05-31 17:18  xing-xing  阅读(236)  评论(0编辑  收藏  举报