题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5638
题意:
给你一个DAG图,删除k条边,使得能个得到字典序尽可能小的拓扑排序
题解:
把拓扑排序的算法稍微改一下,如果某个顶点的入度小于k也把它加到优先队列里面去。
k减小后队列里面会有些点不满足<=k,直接踢出来就好了。
代码:
#include#include #include #include #include #include using namespace std; typedef long long LL; const int maxn = 101010; const int maxm = maxn << 1; const int mod = 1e9 + 7; int n, m, k; vector<int> G[maxn]; int ind[maxn], used[maxn],inq[maxn]; void init() { for (int i = 1; i <= n; i++) G[i].clear(); memset(ind, 0, sizeof(ind)); memset(inq, 0, sizeof(inq)); memset(used, 0, sizeof(used)); } int main() { int tc; scanf("%d", &tc); while (tc--) { scanf("%d%d%d", &n, &m, &k); init(); for (int i = 0; i < m; i++) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); ind[v]++; } priority_queue<int,vector<int>,greater<int> > pq; for (int i = 1; i <= n; i++) { if (ind[i] <= k) pq.push(i),inq[i] = 1; } vector<int> ans; while (!pq.empty()) { while (ind[pq.top()]>k) { inq[pq.top()] = 0; pq.pop(); } int x = pq.top(); pq.pop(); inq[x] = 0; k -= ind[x]; ans.push_back(x); used[x] = 1; for (int i = 0; i < G[x].size(); i++) { int v = G[x][i]; ind[v]--; if (ind[v] <= k&&!inq[v]&&!used[v]) { pq.push(v); inq[v] = 1; } } } LL cnt = 0; for (int i = 0; i < ans.size(); i++) { cnt += (LL)(i + 1)*ans[i]; cnt %= mod; } printf("%lld\n", cnt); } return 0; }