分析:首先,利用贪心可知,如果要所有人的分数和最高,需要把序号大的优先放在前面。其次,对于a的前面不能为b,那么只能a在b前面了,那么就建立一条从a到b的边,并且b的入度加1。然后就是拓扑排序了。要分数最高,则把哪些入度为0的点(他们不需要有哪些人一定要在他们前面,最自由)丢进优先队列,然后就可以实现把序号大的尽量放在前面而且满足题意了。
具体见代码:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <vector> 5 #include <queue> 6 using namespace std; 7 typedef long long ll; 8 9 vector<int> G[100000+5]; 10 int in[100000+5],val[100000+5]; 11 int n,m; 12 void solve() 13 { 14 int sit=1; 15 priority_queue<int> Q; 16 for(int i=1;i<=n;i++) if(!in[i]) Q.push(i); 17 while(!Q.empty()) 18 { 19 int x=Q.top();Q.pop(); 20 val[sit++]=x; 21 for(int i=0;i<G[x].size();i++) 22 { 23 int v = G[x][i]; 24 in[v]--; 25 if(!in[v]) Q.push(v); 26 } 27 } 28 } 29 int main() 30 { 31 int T; 32 scanf("%d",&T); 33 while(T--) 34 { 35 scanf("%d%d",&n,&m); 36 for(int i=1;i<=n;i++) G[i] .clear(); 37 memset(in,0,sizeof(in)); 38 memset(val,0,sizeof(val)); 39 while(m--) 40 { 41 int u,v; 42 scanf("%d%d",&u,&v); 43 G[u].push_back(v); 44 in[v]++; 45 } 46 solve(); 47 int minn=100000+5; 48 ll ans=0; 49 for(int i=1;i<=n;i++) 50 { 51 minn=min(minn,val[i]); 52 ans+=(ll)minn; 53 } 54 printf("%I64d ",ans); 55 } 56 return 0; 57 }