想到了一个分治方法,每一次尽量放小的那个,把它依赖的放在左边,不依赖的放在右边。
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 }