hdu5695 拓扑排序

来源:互联网 发布:兰州知行学院官网 编辑:程序博客网 时间:2024/06/07 16:30

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5695


题目大意:n个人,最开始每个人有一个唯一的ID,从1到N,在排好队之后,每个同学会找出包括自己在内的前方所有同学的最小ID,作为自己评价这堂课的分数。麻烦的是,有一些同学不希望某个(些)同学排在他(她)前面,在满足这个前提的情况下,新晋体育课老师——度度熊,希望最后的排队结果可以使得所有同学的评价分数和最大。


思路: 可以抽象转化一下,若a不希望b在前面,就是a在b的前面,那么假设a到b有一条有向边,是不就转换成了拓扑排序?在用优先级队列维护一下即可。


#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <fstream>#include <algorithm>#include <cmath>#include <queue>#include <stack>#include <vector>#include <map>#include <set>#include <iomanip>using namespace std;//#pragma comment(linker, "/STACK:102400000,102400000")#define maxn 200005#define MOD 1000000007#define mem(a , b) memset(a , b , sizeof(a))#define LL long long#define ULL unsigned long longconst long long INF=0x3fffffff;LL ans ;int n , m;int val[maxn] , in[maxn] , vis[maxn];vector<int>v[maxn];void solve(){    int pos = 1;    priority_queue<int>q;    for(int i = 1 ;i <= n ; i++)    {        if(in[i] == 0)        {            q.push(i);            vis[i] = 1;        }    }    while(!q.empty())    {        int tmp = q.top();        q.pop();        val[pos++] = tmp;        for(int i = 0 ; i < v[tmp].size() ; i ++)        {            in[v[tmp][i]] -- ;            if(!vis[v[tmp][i]] && !in[v[tmp][i]])            {                q.push(v[tmp][i]);                vis[v[tmp][i]] = 1;            }        }    }}int main(){    int t;    scanf("%d" , &t);    while(t--)    {        mem(val , 0);mem(vis , 0) ; mem(in , 0);        scanf("%d %d" , &n , &m);        for(int i = 0 ; i <= n ; i ++) v[i].clear();        int a ,  b;        for(int i = 0 ; i < m ; i ++)        {            scanf("%d %d" , &a , &b);            in[b]++;            v[a].push_back(b);        }        solve();        ans = 0;        int minn = maxn;        for(int i = 1 ; i <= n ; i ++)        {            minn = min(minn , val[i]);            ans += minn;        }        printf("%lld\n" , ans);    }    return 0;}


0 0
原创粉丝点击