一张有向图的拓扑序列是图中点的一个排列,满足对于图中的每条有向边(u→v) 从u 到v ,都满足u 在排列中出现在v 之前。 现在,DZY有一张有向无环图(DAG)。你要在最多删去k 条边之后,求出字典序最大的拓扑序列。
输入有多组数据。 (TestCase≤5 ) 第一行,三个正整数n,m,k(1≤n,m≤105,0≤k≤m) . 接下来m 行,每行两个正整数u,v(u≠v,1≤u,v≤n) , 代表一条有向边(u→v) .
对于每组测试数据,输出一行字典序最大的拓扑序列。
5 5 2 1 2 4 5 2 4 3 4 2 3 3 2 0 1 2 1 3
5 3 1 2 4 1 3 2
数据1. 删除(2->3),(4->5)两条边,可以得到字典序最大的拓扑序列:(5,3,1,2,4).
方法一:使用邻接表存储边
#include <bits/stdc++.h> using namespace std; #define maxn 100000 + 10 #define INF 0x7ffffff #define Lson L, mid, root<<1 #define Rson mid+1, R, root<<1|1 int Min[maxn<<2]; int deg[maxn]; int n, m, k, cnt, num; int head[maxn]; vector<int> vec; ///先明确是利用线段树查询与维护每个点的入度 struct Edge { int v; int next; } edge[maxn]; void init() { num = 0; cnt = 0; memset(head, -1, sizeof(head)); memset(deg, 0, sizeof(deg)); vec.clear(); int u, v; for(int i=0; i<m; i++) { cin>>u>>v; deg[v]++; edge[cnt].v = v; edge[cnt].next = head[u]; head[u] = cnt++; } } void Pushup(int root) { Min[root] = min(Min[root<<1] , Min[root<<1|1]); } void Bulid(int L, int R, int root) { if(L == R) { Min[root] = deg[++num]; return; } int mid = (L+R)>>1; Bulid(Lson); Bulid(Rson); Pushup(root); } void Update(int q, int Deg, int L, int R, int root) { if(L == R) { Min[root] = Deg; return ; } int mid = (L+R)>>1; if(q <= mid) Update(q, Deg, L, mid, root<<1); else Update(q, Deg, mid+1, R, root<<1|1); Pushup(root); } ///查询Min值不大于k的节点 int Query(int L, int R, int root) { if(L==R && Min[root]<=k) return L; int mid = (L+R)>>1; if(Min[root<<1|1] <= k) return Query(Rson); else return Query(Lson); } void topo() { for(int i=1; i<=n; i++) { int id = Query(1, n, 1); vec.push_back(id); k -= deg[id]; deg[id] = INF; Update(id, INF, 1, n, 1); for(int j=head[id]; j!=-1; j=edge[j].next) { int v = edge[j].v; deg[v]--; Update(v, deg[v], 1, n, 1); } } } int main() { while(~scanf("%d%d%d", &n, &m, &k)) { init(); Bulid(1, n, 1); topo(); for(int i=0; i<vec.size(); i++) { cout<<vec[i]; if(i != vec.size()-1) cout<<" "; else cout<<endl; } } return 0; }
方法二:使用vector存储边
#include <bits/stdc++.h> using namespace std; #define maxn 100000 + 10 #define INF 0x7ffffff #define root 1, n, 1 #define Lson L, mid, rt<<1 #define Rson mid+1, R, rt<<1|1 int t, k, n, m; int deg[maxn]; int Min[maxn<<2]; vector<int> G[maxn]; vector<int> vec; void Pushup(int rt) { Min[rt] = min(Min[rt<<1] , Min[rt<<1|1]); } void Bulid(int L, int R, int rt) { if(L == R) { Min[rt] = deg[++t]; return ; } int mid = (L+R)>>1; Bulid(Lson); Bulid(Rson); Pushup(rt); } void Update(int q, int deg, int L, int R, int rt) { if(L == R) { Min[rt] = deg; return; } int mid = (L+R)>>1; if(q <= mid) Update(q, deg, Lson); else Update(q, deg, Rson); Pushup(rt); } int Query(int L, int R, int rt) { if(L==R && Min[rt]<=k) return L; int mid = (L+R)>>1; if(Min[rt<<1|1] <= k) return Query(Rson); else return Query(Lson); } void init() { t = 0; vec.clear(); memset(deg, 0,sizeof(deg)); for(int i=1; i<=n; i++) G[i].clear(); int u, v; for(int i=0; i<m; i++) { cin>>u>>v; G[u].push_back(v); deg[v]++; } } void topo() { for(int i=1; i<=n; i++) { int id = Query(root); vec.push_back(id); k -= deg[id]; deg[id] = INF; Update(id, INF, root); for(int j=0; j<G[id].size(); j++) { int v = G[id][j]; deg[v]--; Update(v, deg[v], root); } } } int main() { while(~scanf("%d%d%d", &n, &m, &k)) { init(); Bulid(root); topo(); for(int i=0; i<vec.size(); i++) { cout<<vec[i]; if(i != vec.size()-1) cout<<" "; else cout<<endl; } } return 0; }
BC DZY Loves Topological Sorting
原文地址:http://blog.csdn.net/dojintian/article/details/44891803