HDU 5195 DZY Loves Topological Sorting 拓扑排序
题目链接:
hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5195
bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=573&pid=1002
题解:
1、拓扑排序+贪心
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<queue> 7 using namespace std; 8 9 const int maxn = 1e5 + 10; 10 const int INF = 0x3f3f3f3f; 11 12 int n, m, k; 13 14 struct Node { 15 int v, flag; 16 Node(int v,int flag=0):v(v),flag(flag){} 17 Node() { flag = 0; } 18 }; 19 20 vector<Node> head[maxn]; 21 int ind[maxn],done[maxn]; 22 23 void init() { 24 for (int i = 0; i < n; i++) { 25 ind[i] = done[i]=0; 26 head[i].clear(); 27 } 28 } 29 30 int main() { 31 while (scanf("%d%d%d", &n, &m, &k) == 3 && n) { 32 init(); 33 for (int i = 0; i < m; i++) { 34 int u, v; 35 scanf("%d%d", &u, &v); u--, v--; 36 ind[v]++; 37 head[u].push_back(Node(v,0)); 38 } 39 40 priority_queue<int> pq; 41 42 //删边 43 for (int i = n - 1; i >= 0; i--) { 44 if (k >= ind[i]) { 45 //将i的父亲ui中,满足ui<i,即边(ui,i)删了,这里要注意,对于边(ui,i),ui>i的边,根本不用删 46 k -= ind[i]; 47 pq.push(i); 48 for (int j = 0; j < head[i].size(); j++) { 49 Node &nd = head[i][j]; 50 if (i > nd.v) { 51 //把边(i,v)删了,拓扑排序的时候不能再走这条边了 52 nd.flag = 1; 53 ind[nd.v]--; 54 } 55 } 56 } 57 } 58 59 vector<int> ans; 60 //拓扑排序 61 while (!pq.empty()) { 62 int u = pq.top(); pq.pop(); 63 if (done[u]) continue; 64 ans.push_back(u); 65 done[u] = 1; 66 for (int i = 0; i < head[u].size(); i++) { 67 Node& nd = head[u][i]; 68 if (done[nd.v]||nd.flag) continue; 69 ind[nd.v]--; 70 if (ind[nd.v] == 0) pq.push(nd.v); 71 } 72 } 73 74 printf("%d", ans[0]+1); 75 for (int i = 1; i < ans.size(); i++) printf(" %d", ans[i]+1); 76 printf("\n"); 77 } 78 return 0; 79 } 80 /* 81 5 3 1 82 4 3 83 1 3 84 3 2 85 86 5 3 0 87 4 3 88 1 3 89 3 2 90 */
2、线段树+贪心
对于节点i,入度为ind[i],则可以这样贪心:对于1<=i<=n,求最大的i使得ind[i]<=k,我们可以把入度数组做成线段树,维护最小入度,二分查找,优先搜右边(右边的i会更大),找到以后,吧对于的子节点vj的入度减1,k-=ind[i]。这样一直做n次就能得到答案。
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<algorithm> 5 #define lson (o<<1) 6 #define rson ((o<<1)+1) 7 #define M (l+(r-l)/2) 8 using namespace std; 9 10 const int maxn = 1e5 + 10; 11 const int INF = 0x3f3f3f3f; 12 13 int n, m, k; 14 15 vector<int> head[maxn]; 16 int ind[maxn<<2],minv[maxn<<2]; 17 18 int _pos, _v; 19 void update(int o, int l, int r) { 20 if (l==r) { 21 ind[o] += _v; 22 minv[o] = ind[o]; 23 } 24 else { 25 if (_pos <= M) update(lson, l, M); 26 else update(rson, M + 1, r); 27 minv[o] = min(minv[lson], minv[rson]); 28 } 29 } 30 31 void query(int o, int l, int r,int &res) { 32 if (l == r) { 33 if (ind[o] <= k) { 34 k -= ind[o]; 35 res = l; 36 } 37 } 38 else { 39 //printf("lson:%d,rson:%d\n",minv[lson],minv[rson]); 40 if (k >= minv[rson]) query(rson, M + 1, r,res); 41 else if (k >= minv[lson]) query(lson, l, M,res); 42 } 43 } 44 45 void init() { 46 for (int i = 1; i <= n; i++) head[i].clear(); 47 memset(ind, 0, sizeof(ind)); 48 memset(minv,0,sizeof(minv)); 49 } 50 51 int main() { 52 while (scanf("%d%d%d", &n, &m, &k) == 3 && n) { 53 init(); 54 for (int i = 0; i < m; i++) { 55 int u, v; 56 scanf("%d%d", &u, &v); 57 head[u].push_back(v); 58 _pos = v, _v = 1; 59 update(1, 1, n); 60 } 61 //puts("after update"); 62 vector<int> ans; 63 for (int i = 0; i < n; i++) { 64 int res; 65 query(1, 1, n, res); 66 //puts("after first qurey!"); 67 //printf("res:%d\n", res); 68 ans.push_back(res); 69 for (int j = 0; j < head[res].size(); j++) { 70 _pos = head[res][j], _v = -1; 71 update(1, 1, n); 72 //puts("after first upate"); 73 } 74 _pos = res, _v = INF; 75 update(1, 1, n); 76 } 77 //puts("ans is zero"); 78 printf("%d", ans[0]); 79 for (int i = 1; i < ans.size(); i++) printf(" %d", ans[i]); 80 printf("\n"); 81 } 82 return 0; 83 }