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 }
View Code

 

 

  正解:

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

 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 }
View Code

 

posted @ 2015-12-30 21:22  y7070  阅读(243)  评论(0编辑  收藏  举报