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;
}