bzoj4010: [HNOI2015]菜肴制作【拓扑排序】

  想到了一个分治方法,每一次尽量放小的那个,把它依赖的放在左边,不依赖的放在右边。

  TLE 80:

 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define drep(i, a, b) for (int i = a; i >= b; i--)
 4 #define REP(i, a, b) for (int i = a; i < b; i++)
 5 #define mp make_pair
 6 #define pb push_back
 7 #define clr(x) memset(x, 0, sizeof(x))
 8 #define xx first
 9 #define yy second
10 using namespace std;
11 typedef long long i64;
12 typedef pair<int, int> pii;
13 const int inf = ~0U >> 1;
14 const i64 INF = ~0ULL >> 1;
15 //***********************************
16
17 const int maxn = 100005;
18
19 vector <int> Vx[maxn], Vy[maxn];
20 int src[maxn], lft[maxn];
21
22 int n, m;
23 int deg[maxn], tmp[maxn];
24
25 bool topo() {
26     static int que[maxn]; int qh(0), qt(0);
27     rep(i, 1, n) if (!deg[i]) que[++qt] = i;
28     int cnt(0);
29     while (qh != qt) {
30         int x = que[++qh];
31         ++cnt;
32         int len = (int) Vx[x].size();
33         for (int i = 0; i < len; i++) {
34             if (--deg[Vx[x][i]] == 0) que[++qt] = Vx[x][i];
35         }
36     }
37     return cnt == n;
38 }
39
40 bool vis[maxn];
41 void bfs(int s) {
42     static int que[maxn]; int qh(0), qt(0);
43     vis[que[++qt] = s] = 1;
44     while (qh != qt) {
45         int x = que[++qh];
46         int len = (int) Vy[x].size();
47         for (int i = 0; i < len; i++) {
48             if (!vis[Vy[x][i]]) {
49                 vis[que[++qt] = Vy[x][i]] = 1;
50                 lft[Vy[x][i]] = 1;
51             }
52         }
53     }
54 }
55
56 void solve(int l, int r) {
57     if (l >= r) return;
58     int t, haha = inf;
59     rep(i, l, r) if (src[i] < haha) { t = i; haha = src[i]; }
60     rep(i, l, r) lft[src[i]] = vis[src[i]] = 0;
61     bfs(src[t]);
62     int cur = l - 1;
63     rep(i, l, r) if (src[i] != src[t] && lft[src[i]]) tmp[++cur] = src[i];
64     tmp[++cur] = src[t]; int mid = cur;
65     rep(i, l, r) if (src[i] != src[t] && !lft[src[i]]) tmp[++cur] = src[i];
66     memcpy(src + l, tmp + l, sizeof(int) * (r - l + 1));
67     solve(l, mid - 1);
68     solve(mid + 1, r);
69 }
70
71 int main() {
72     freopen("dishes.in", "r", stdin);
73     freopen("dishes.out", "w", stdout);
74     int T; scanf("%d", &T);
75     while (T--) {
76         scanf("%d%d", &n, &m);
77         rep(i, 1, n) Vx[i].clear(), Vy[i].clear();
78         clr(deg);
79         rep(i, 1, m) {
80             int x, y; scanf("%d%d", &x, &y);
81             Vx[x].pb(y);
82             Vy[y].pb(x);
83             deg[y]++;
84         }
85         if (!topo()) { puts("Impossible!"); continue; }
86         rep(i, 1, n) src[i] = i;
87         solve(1, n);
88         rep(i, 1, n) printf(i == n ? "%d\n" : "%d ", src[i]);
89     }
90     return 0;
91 }

  正解:

    有依赖关系,我们建立反图,加入我们的到了这个反图的一个拓扑序,那么怎样对应到最优的答案呢?应该是尽量让编号小的出现在队列后方,所以最大字典序的拓扑排序即可。

 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define drep(i, a, b) for (int i = a; i >= b; i--)
 4 #define REP(i, a, b) for (int i = a; i < b; i++)
 5 #define mp make_pair
 6 #define pb push_back
 7 #define clr(x) memset(x, 0, sizeof(x))
 8 #define xx first
 9 #define yy second
10 using namespace std;
11 typedef long long i64;
12 typedef pair<int, int> pii;
13 const int inf = ~0U >> 1;
14 const i64 INF = ~0ULL >> 1;
15 //***********************************
16
17 const int maxn = 100005;
18
19 vector <int> Vx[maxn], Vy[maxn];
20 priority_queue<int> Q;
21 int deg[maxn], ans[maxn], n, m;
22
23 bool topo() {
24     rep(i, 1, n) if (!deg[i]) Q.push(i);
25     int cnt(0);
26     while (!Q.empty()) {
27         int x = Q.top(); Q.pop();
28         ans[++cnt] = x;
29         int len = (int) Vy[x].size();
30         for (int i = 0; i < len; i++) {
31             if (--deg[Vy[x][i]] == 0) Q.push(Vy[x][i]);
32         }
33     }
34     return cnt == n;
35 }
36
37 int main() {
38     freopen("dishes.in", "r", stdin);
39     freopen("dishes.out", "w", stdout);
40     int T; scanf("%d", &T);
41     while (T--) {
42         scanf("%d%d", &n, &m);
43         rep(i, 1, n) Vx[i].clear(), Vy[i].clear();
44         clr(deg);
45         rep(i, 1, m) {
46             int x, y; scanf("%d%d", &x, &y);
47             Vx[x].pb(y);
48             Vy[y].pb(x);
49             deg[x]++;
50         }
51         if (!topo()) puts("Impossible!");
52         else { drep(i, n, 1) printf("%d ", ans[i]); puts(""); }
53     }
54     return 0;
55 }

时间: 2024-10-11 19:24:22

bzoj4010: [HNOI2015]菜肴制作【拓扑排序】的相关文章

BZOJ4010 HNOI2015 菜肴制作 拓扑排序+贪心

题意:给定限制条件(a,b)表示a必须在b之前,求所有合法序列中,小的数尽量在前面的方案 题解:首先我们根据限制条件建反向图,然后在反向图上求字典序最小的拓扑序(队列改为堆),逆序输出即可. #include <queue> #include <functional> #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include

【BZOJ4010】[HNOI2015]菜肴制作 拓扑排序

[BZOJ4010][HNOI2015]菜肴制作 Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予1到N的顺序编号,预估质量最高的菜肴编号为1.由于菜肴之间口味搭配的问题,某些菜肴必须在另一些菜肴之前制作,具体的,一共有 M 条形如“i 号菜肴‘必须’先于 j 号菜肴制作”的限制,我们将这样的限制简写为<i,j>.现在,酒店希望能求出一个最优的菜肴的制作顺序,使得小 A能尽量先吃到质量

bzoj 4010: [HNOI2015]菜肴制作 拓扑排序

4010: [HNOI2015]菜肴制作 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/67 Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予 1到N的顺序编号,预估质量最高的菜肴编号为1.由于菜肴之间口味搭配的问题, 某些菜肴必须在另一些菜肴之前制作,具体的,一共有 M 条形如“i 号菜肴‘必须’

BZOJ 4010 HNOI2015 菜肴制作 拓扑排序+堆

题目大意:给定一张无向图,求一个拓扑序,使: 1的位置最靠前 在保证上面的条件下使2的位置最靠前 在保证上面的条件下使3的位置最靠前 -- 注意不是字典序最小!例如样例3 建立反图,对反图求字典序最大的拓扑序,然后反向输出即可. 我不知道为什么.真的不知道. 求个解答在线等. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 1001

cogs1958 菜肴制作 拓扑排序

链接:http://cogs.pro/cogs/problem/problem.php?pid=1958 题意:给出一些约束条件,要求得出字典序最小的符合所有条件的方案. 这道题很显然是一个在$AOE$上的程序流程问题,显然是一个拓扑排序.但是这个拓扑排序有点意思,因为它要求字典序最小. 那么我们就要找出一种方法,使得最小的出现在最前面,那么我们就考虑用堆维护,倒序建边. 如果我们正序建边,很有可能我们选取了一个点之后再向下走发现了一个更小的点,而且这个更小的点还是可以放在前面的.而如果倒序建边

B4010 菜肴制作 拓扑排序(附随机跳题代码)

今天写了一个自己的随机跳题小程序,第一次试发现跳的全是不可做题,但是在周围我一眼看见了这个题,不能说一眼看出来,但是也是比较有思路,所以就做他了! 做得比较顺利,做完之后美滋滋,突然发现样例第三组过不了...然后发现自己算法有问题...GG,又想了一个超复杂的算法,刚开始写就放弃了,根本没法写. 于是看题解(本来以为自己能A),就看了一行就明白了,只要倒着存边再倒着输出就行了!!!QAQ!! 跳题代码: #include<iostream> #include<cstdio> #in

bzoj4010: [HNOI2015]菜肴制作

做法是求逆拓扑序中字典序最大的将其反转则得到答案,粗略理解为对于每个数,把能把比大的能够放在他右边的都放在了右边,所以答案最优. 留坑在此 数据太水第一次du没清零都过了? 1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 #include<vector> 7 8 using n

bzoj 4010: [HNOI2015]菜肴制作(优先队列+拓扑排序)

4010: [HNOI2015]菜肴制作 Time Limit: 5 Sec  Memory Limit: 512 MB Submit: 1199  Solved: 583 [Submit][Status][Discuss] Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予 1到N的顺序编号,预估质量最高的菜肴编号为1.由于菜肴之间口味搭配的问题, 某些菜肴必须在另一些菜肴之前制作,具体

【BZOJ 4010】 [HNOI2015]菜肴制作

4010: [HNOI2015]菜肴制作 Time Limit: 5 Sec Memory Limit: 512 MB Submit: 426 Solved: 242 [Submit][Status][Discuss] Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予 1到N的顺序编号,预估质量最高的菜肴编号为1.由于菜肴之间口味搭配的问题, 某些菜肴必须在另一些菜肴之前制作,具体的,一