hdoj-5695-Gym Class

来源:互联网 发布:矩阵函数的导数和积分 编辑:程序博客网 时间:2024/06/14 11:10

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

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

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

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

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

Output
对于每组数据,输出最大分数 。
 

Sample Input
31 02 11 23 13 1
 

Sample Output
126

拓扑排序

利用贪心可知,如果要所有人的分数和最高,需要把序号大的优先放在前面。其次,对于a的前面不能为b,那么只能a在b前面了


    #include<cstdio>    #include<cstring>    #include<iostream>    #include<algorithm>    #include<queue>    #include<vector>    using namespace std;    typedef long long ll;    #define maxn 100005    vector<int>v[maxn];    int d[maxn],w[maxn];    int a,b,x,y;    void topsort()    {        int k=1;        //printf("a=%d b=%d\n",a,b);        priority_queue<int>q;        //for(int i=1;i<=a;i++) printf("%d\n",d[i]);        for(int i=1;i<=a;i++) if(!d[i]) q.push(i);        while(!q.empty())        {            int t=q.top();            q.pop();            w[k++]=t;            for(int i=0;i<v[t].size();i++)            {                int cnt=v[t][i];                d[cnt]--;                if(!d[cnt]) q.push(cnt);            }        }    }    int main()    {        int t;        scanf("%d",&t);        while(t--)        {            scanf("%d%d",&a,&b);            for(int i=1;i<=a;i++) v[i] .clear();            memset(d,0,sizeof(d));            memset(w,0,sizeof(w));            while(b--)            {                scanf("%d%d",&x,&y);                v[x].push_back(y);                d[y]++;            }            topsort();            int minn=maxn;            ll ans=0;            for(int i=1;i<=a;i++)            {                minn=min(minn,w[i]);                ans+=(ll)minn;            }            printf("%I64d\n",ans);        }        return 0;    }


0 0