思路:这道题如果不考虑两位同学两两间相互讨厌,那么直接贪心就可以了,但是增加了两两间相互讨厌,那么可以把它们之间的这种关系建图来模拟。如果a不希望b排在他的前面,则a与b建一条a指向b的有向边。那么这就有点像拓扑排序了(网上说这是拓扑排序,我觉得只能说思路有点像)。然后先把入度为0的放入优先队列(由大到小),因为入度为0说明没有人不喜欢他站在前面,所以直接可以排,但是要满足贪心策略,所以优先队列从小到大,然后放入队列中的节点的儿子节点的入度减一,重复刚才的步骤。
参考:http://blog.csdn.net/queuelovestack/article/details/51471639
代码:
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e5+50;
vector<int> g[maxn];
int indgree[maxn],u,v,mins;
long long ans;
int t,n,m;
int main(){
while(scanf("%d",&t)!=EOF){
for(int cas=1;cas<=t;cas++){
memset(g,0,sizeof(g));
memset(indgree,0,sizeof(indgree));
mins=inf;
ans=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
g[u].push_back(v);
indgree[v]++;
}
priority_queue<int,vector<int> >q;
for(int i=1;i<=n;i++){
if(!indgree[i]){
q.push(i);
}
}
while(!q.empty()){
int temp=q.top();q.pop();
mins=min(mins,temp);
ans+=mins;
for(int i=0;i<g[temp].size();i++){
int son=g[temp][i];
indgree[son]--;
if(!indgree[son])
q.push(son);
}
}
printf("%lld\n",ans);
}
}
return 0;
}