题目链接;
HDU 5695 Gym Class
题意:
定义序列每个元素的权值是在他之前包括自己的最小数。求序列权值和最大的拓扑排序。
数据范围:
n≤105,m≤105
。
分析;
也就是每次从度为
0
<script type="math/tex" id="MathJax-Element-74">0</script>的点中我们尽可能要得到编号大的点。优先队列搞下就好了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <ctime>
#include <cassert>
#include <vector>
#include <queue>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N = 100010;
int degree[MAX_N], ans[MAX_N];
vector<int> vec[MAX_N];
priority_queue<int> que;
void TopoSort(int n)
{
for(int i = 1; i <= n; ++i) {
if(degree[i] == 0) que.push(i);
}
int total = 1;
while(!que.empty()) {
int cur = que.top();
que.pop();
ans[total++] = cur;
for(int i = 0; i < vec[cur].size(); ++i) {
int to = vec[cur][i];
degree[to]--;
if(degree[to] == 0) que.push(to);
}
}
}
int main()
{
int T, n, m;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
for(int i = 0; i <= n; ++i) {
degree[i] = 0;
vec[i].clear();
}
for(int i = 0; i < m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
degree[v]++;
vec[u].push_back(v);
}
TopoSort(n);
ll sum = ans[1];
for(int i = 2; i <= n; ++i) {
ans[i] = min(ans[i], ans[i - 1]);
sum += ans[i];
}
printf("%lld\n", sum);
}
return 0;
}