题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5695
题解:
求出字典序最大的拓扑序。然后把求好的数列翻转过来就是满足条件的数列,然后模拟求一下value就可以了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std; const int maxn = 1e5 + ;
typedef long long LL; struct Edge {
int v, ne;
Edge(int v, int ne) :v(v), ne(ne) {}
Edge() {}
}egs[maxn*]; int n, m;
int head[maxn], ind[maxn],tot; void addEdge(int u, int v) {
egs[tot] = Edge(v, head[u]);
head[u] = tot++;
} void init() {
tot = ;
memset(ind, , sizeof(ind));
memset(head, -, sizeof(head));
} int main() {
int tc;
scanf("%d", &tc);
while (tc--) {
init();
scanf("%d%d", &n, &m);
for (int i = ; i < m; i++) {
int u, v;
scanf("%d%d", &u, &v);
addEdge(u, v);
ind[v]++;
}
priority_queue<int> pq;
for (int i = ; i <= n; i++) {
if (ind[i] == ) pq.push(i);
}
vector<int> ans;
while (!pq.empty()) {
int u = pq.top(); pq.pop();
ans.push_back(u);
int p = head[u];
while (p != -) {
Edge& e = egs[p];
ind[e.v]--;
if (ind[e.v] == ) {
pq.push(e.v);
}
p = e.ne;
}
}
LL sum = ans[]; int mi = ans[];
for (int i = ; i < ans.size(); i++) {
mi = min(mi, ans[i]);
sum += mi;
}
printf("%lld\n", sum);
}
return ;
}