拓扑排序+优先队列

来源:互联网 发布:触摸屏软件下载 编辑:程序博客网 时间:2024/06/05 07:54
Gym Class
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit Status Practice HDU 5695

Description

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

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

Input

第一行一个整数$T$,表示$T(1 \leq T \leq 30)$ 组数据。 

对于每组数据,第一行输入两个整数$N$和$M (1 \leq N \leq 100000, 0 \leq M \leq 100000)$,分别表示总人数和某些同学的偏好。 

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

Output

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

Sample Input

31 02 11 23 13 1

Sample Output

12

6

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
#include<cstdio>#include<queue>#include<algorithm>using namespace std;int in[1000005];//入度 vector<int>G[1000005];//动态存储--二维 int main(){int n,m,t;scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)G[i].clear(),in[i]=0;//初始化,清零 for(int i=1;i<=m;i++){int a,b;scanf("%d%d",&a,&b);G[a].push_back(b);in[b]++;}priority_queue<int,vector<int>,less<int> >q;//优先队列 //入度为0的有多个,大的先入列 for(int i=1;i<=n;i++){if(in[i]==0)q.push(i);}long long ans=0;int Min=n+1;while(!q.empty())        {        int u=q.top();q.pop();        Min=min(Min,u);        ans+=Min;        for(int i=0;i<G[u].size();i++)        {        int v=G[u][i];        if(--in[v]==0)        q.push(v);}}printf("%lld\n",ans);}return 0;}

0 0
原创粉丝点击