
拓扑排序
题意:给定一个上三角矩阵代表一个数列,其中 aij 代表数组元素和 sum[i⋯j] 的正负,求出一个符合条件的数列。
这是一道构造题,因此只要确定一种可行解即可。
对于一段区间的元素和,自然想到可以理解为两个前缀和的差,而一旦将所有前缀和都求出来了,就可以构造出一组可行解了。
将每一个前缀和 sum[1⋯i] 视为节点,矩阵中每一个元素视为边,若为正,则代表 sumj−sumi>0 ,即 sumj>sumi ,这样一个偏序关系可以用拓扑序来构造出可行解,只要将所有大小关系都表现在边上,最终一定可以找到一个拓扑序列,满足矩阵的所有元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include<bits/stdc++.h> using namespace std; #define ll long long typedef pair<int, int> pii; const int INF = 0x3f3f3f3f; const int maxn = 1e4 + 10; int T; int n; char mz[20][20]; vector<int>G[20]; bool vis[20]; int ans[20]; void dfs(int u) { vis[u] = 1; for (int v : G[u]) { if (!vis[v]) { dfs(v); } ans[u] = max(ans[u],ans[v] + 1); } } int main() { scanf("%d", &T); while (T--) { scanf("%d", &n); memset(vis, 0, sizeof(vis)); memset(ans, 0, sizeof(ans)); for (int i = 0; i <= n; i++)G[i].clear(); for (int i = 1; i <= n; i++) { for (int j = i; j <= n; j++) { scanf(" %c", &mz[i][j]); } } for (int i = 1; i <= n; i++) { for (int j = i; j <= n; j++) { if (mz[i][j] == '-')G[i - 1].push_back(j); else if (mz[i][j] == '+')G[j].push_back(i - 1); } } for (int i = 0; i <= n; i++) { if (!vis[i])dfs(i); } for (int i = 1; i <= n; i++)printf("%d ", ans[i] - ans[i - 1]); printf("\n"); } return 0; }
|