天天看點

HDU 5695 Gym Class

Problem 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

6

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<bitset>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 10;
int T, cas = 1;
int n, ct[maxn], m, x, y;
int ft[maxn], nt[maxn], u[maxn], sz;
int res;
LL ans;

int main()
{
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d", &n, &m);
        sz = 0;
        for (int i = 1; i <= n; i++) ct[i] = 0, ft[i] = -1;
        for (int i = 0; i < m; i++)
        {
            scanf("%d%d", &x, &y);
            u[sz] = y;    nt[sz] = ft[x]; ft[x] = sz++; ct[y]++;
        }
        ans = 0;    res = n;
        priority_queue<int> p;
        for (int i = 1; i <= n; i++) if (!ct[i]) p.push(i);
        while (!p.empty())
        {
            int q = p.top();    p.pop();
            res = min(res, q);    ans += res;
            for (int i = ft[q]; i != -1; i = nt[i])
            {
                if (!(--ct[u[i]])) p.push(u[i]);
            }
        }
        printf("%I64d\n", ans);
    }
    return 0;
}