HDU 5695 Gym Class && 百度之星 初赛 1006
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5695
本文链接:http://www.cnblogs.com/Ash-ly/p/5515234.html
题意:
第 一次上课之前,所有同学要排成一列,假设最开始每个人有一个唯一的ID,从1到N在排好队之后,每个同学会找出包括自己在内的前方所有同学的最小ID,作 为自己评价这堂课的分数.麻烦的是,有一些同学不希望某个(些)同学排在他(她)前面,在满足这个前提的情况下,新晋体育课老师——度度熊,希望最后的排 队结果可以使得所有同学的评价分数和最大.
第一行输入T,表示有T组数据.对于每组数据的第一行有两个数字N和M,代表总人数和某些同学的偏好,接下来M行,有两个数字A和B表示A不想让B站在他的前面.对于每组输入输出最大分数.
思路:
如果A不想让B在他的前面,那么就可以认为A到B有一条有向边,那么就可以利用拓扑序列来做这道题了,但是要想每次首先访问到的是能访问到的中的最大值,那么可以把入度为零的所有点压入优先队列中,使得每次新的拓展节点是能拓展的种的最大值.
代码:
1 #include <iostream> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <queue> 8 #include <stack> 9 #include <vector> 10 using namespace std; 11 typedef long long LL; 12 const int MAXN = 100000; 13 vector<int> map[MAXN + 7];//图 14 int inder[MAXN + 7];//入度 15 16 int main(){ 17 //freopen("input.txt", "r", stdin); 18 int T; 19 scanf("%d", &T); 20 while(T--){ 21 int n, m; 22 scanf("%d%d", &n, &m); 23 for(int i = 1; i <= n; i++)map[i].clear(); 24 memset(inder, 0, sizeof(inder)); 25 for(int i = 1; i <= m; i++){ 26 int u, v; 27 scanf("%d%d", &u, &v); 28 map[u].push_back(v); // u 到 v 有一条有向边 29 inder[v]++; 30 } 31 priority_queue<int> Qu; 32 for(int i = 1; i <= n; i++) if(!inder[i]) Qu.push(i);//刚开始所有入度为0的点进队 33 LL ans = 0; 34 int minu = n + 1; 35 while(!Qu.empty()){ 36 int head = Qu.top(); //获得下一个待扩展节点,一定是当前可扩展节点中最大的 37 Qu.pop(); 38 minu = min(minu, head);//每个人的分数等于他以及他之前的人的编号的最小值 39 ans +=(LL) minu; 40 for(int i = 0; i < map[head].size(); i++) 41 if( !(--inder[map[head][i]]) )//每访问一个点,就把从这个点出发的有向边删除,删除后出现新的入度为0的点,则进队 42 Qu.push(map[head][i]); 43 } 44 printf("%lld\n", ans); 45 } 46 return 0; 47 }
It's not numeral,character and punctuation .It's my life.