Description
众所周知,度度熊喜欢各类体育活动。
今天,它终于当上了梦寐以求的体育课老师。第一次课上,它发现一个有趣的事情。在上课之前,所有同学要排成一列, 假设最开始每个人有一个唯一的ID,从1到N,在排好队之后,每个同学会找出包括自己在内的前方所有同学的最小ID,作为自己评价这堂课的分数。麻烦的是,有一些同学不希望某个(些)同学排在他(她)前面,在满足这个前提的情况下,新晋体育课老师——度度熊,希望最后的排队结果可以使得所有同学的评价分数和最大。
Input
第一行一个整数T,表示T(1≤T≤30) 组数据。
对于每组数据,第一行输入两个整数N和M(1≤N≤100000,0≤M≤100000),分别表示总人数和某些同学的偏好。
接下来M行,每行两个整数A 和B(1≤A,B≤N),表示ID为A的同学不希望ID为B的同学排在他(她)之前。你可以认为题目保证至少有一种排列方法是符合所有要求的。
Output
对于每组数据,输出最大分数 。
Sample Input
3
1 0
2 1
1 2
3 1
3 1
Sample Output
1
2
6
思路:我们对于这个进行一下拓扑排序,然后贪心的每次加入一个最大的
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 #define inf 0x3f3f3f3f 5 const int maxn = 110000; 6 int n,m; 7 int stk[maxn],in[maxn];//stk里面存拓扑排序,in表示入度 8 vector<int> e[maxn]; 9 priority_queue <int> q; 10 void init () 11 { 12 memset(stk,0,sizeof stk); 13 memset(in,0,sizeof in); 14 for (int i=0;i<maxn;++i) 15 e[i].clear(); 16 while (!q.empty()) q.pop(); 17 } 18 int main() 19 { 20 //freopen("de.txt","r",stdin); 21 int T; 22 scanf("%d",&T); 23 while (T--){ 24 scanf("%d%d",&n,&m); 25 init(); 26 for (int i=0;i<m;++i){ 27 int x,y; 28 scanf("%d%d",&x,&y); 29 e[x].push_back(y); 30 in[y]++; 31 } 32 for (int i=1;i<=n;++i) 33 if (in[i]==0) q.push(i); 34 int tot = 0; 35 while (!q.empty()){ 36 int now = q.top(); 37 q.pop(); 38 stk[tot++]=now; 39 for (int i=0;i<e[now].size();++i){ 40 int nxt = e[now][i]; 41 in[nxt]--; 42 if (in[nxt]==0) 43 q.push(nxt); 44 } 45 } 46 long long ans = 0; 47 int tmp = inf; 48 for (int i=0;i<n;++i){ 49 tmp = min(tmp,stk[i]); 50 ans+=tmp; 51 } 52 printf("%lld ",ans); 53 } 54 return 0; 55 }